禁止拷贝构造函数和赋值操作符

不积跬步无以至千里 / 2024-10-19 / 原文

 

GlobalSettings(const GlobalSettings&) = delete;
GlobalSettings& operator=(const GlobalSettings&) = delete;

这两行代码是为了禁止拷贝构造函数赋值操作符,也就是说,GlobalSettings 类的对象无法通过拷贝赋值来创建或修改。这是为了防止类的实例被复制,通常用于实现单例模式或其他需要保证唯一实例的场景。

让我们详细解释一下:

1. GlobalSettings(const GlobalSettings&) = delete;

  • 作用:删除默认的拷贝构造函数。

  • 拷贝构造函数:如果没有显式定义,编译器会自动生成一个拷贝构造函数,其作用是通过现有对象来创建一个新对象。它的签名通常是 ClassName(const ClassName&),其中 const ClassName& 是一个对已有对象的引用。

    例如:

    GlobalSettings gs1;
    GlobalSettings gs2(gs1);  // 这将调用拷贝构造函数
    

    通过 delete 关键字,你显式地告诉编译器删除这个拷贝构造函数,这意味着对象不能通过拷贝来构造。尝试复制对象会导致编译错误。

  • 用途:禁止拷贝构造函数可以防止类对象被拷贝。例如,在实现单例模式时,您希望只存在一个全局对象,因此需要防止通过拷贝来创建额外的实例。

2. GlobalSettings& operator=(const GlobalSettings&) = delete;

  • 作用:删除赋值操作符。

  • 赋值操作符:默认的赋值操作符允许将一个对象赋值给另一个对象,签名通常是 ClassName& operator=(const ClassName&),并返回一个对该类对象的引用。

    例如:

    GlobalSettings gs1;
    GlobalSettings gs2;
    gs2 = gs1;  // 这将调用赋值操作符
    

    通过 delete 关键字,你显式地禁止使用赋值操作符,因此尝试将一个对象赋值给另一个对象将导致编译错误。

  • 用途:通过删除赋值操作符,可以确保对象之间不能通过赋值进行拷贝或替换。这对保护对象的唯一性很重要,尤其是在类中包含需要特殊管理的资源(如文件句柄、线程、内存等)时。

总结:

这两行代码的意思是,GlobalSettings 类的对象不能被拷贝或通过赋值进行修改。它通常用于防止在程序中产生多个实例,比如在单例模式中,确保类只有一个全局实例。

示例应用场景:单例模式

在单例模式中,您通常希望一个类只能有一个实例,并且该实例不能被复制或重新赋值。这时候可以删除拷贝构造函数和赋值操作符:

class GlobalSettings {
public:
    static GlobalSettings& getInstance() {
        static GlobalSettings instance;  // 唯一的实例
        return instance;
    }

    // 禁止拷贝构造和赋值操作
    GlobalSettings(const GlobalSettings&) = delete;
    GlobalSettings& operator=(const GlobalSettings&) = delete;

private:
    GlobalSettings() {}  // 私有构造函数,防止直接实例化
};
  • 通过这种方式,您只能通过 getInstance() 来获取 GlobalSettings 的唯一实例。
  • 任何尝试通过拷贝或赋值来创建或修改 GlobalSettings 对象都会导致编译错误。