首先要知道拷贝的场景:拷贝构造函数以及赋值运算符重载,想要让一个类禁止拷贝,只需让该类不能调用拷贝构造函数以及赋值运算符重载即可。
方法1:将这两个函数只声明,不定义(防止编译器默认生成,但不能防止用户可在外面定义),或者把这两个函数设置为私有。
方法2:C++11的方式将这两个函数删除(用delete)。
例如:
class Copyban
{
public:Copyban():_a(99){}
private://Copyban(Copyban&);//Copyban& operator=(const Copyban&);Copyban(Copyban&) = delete;Copyban& operator=(const Copyban&) = delete;int _a;
};
class HeapOnly
{
public:static HeapOnly* CreateObj(){return new HeapOnly;}
private:HeapOnly(){}HeapOnly(const HeapOnly&);//HeapOnly(const HeapOnly&) = delete;
};
class StackOnly
{
public:static StackOnly CreateObj(){return StackOnly();}
private://StackOnly(StackOnly&) = delete;StackOnly(){}
};
但无法防止在外面拷贝构造在创建对象。
StackOnly obj1 = StackOnly::CreateObj(); static StackOnly obj2(obj1); //在静态区拷贝构造对象 StackOnly* ptr = new StackOnly(obj1); //在堆上拷贝构造对象
方法2:
屏蔽operator new函数和operator delete函数,同时把构造函数私有化,用静态函数返回对象
new和delete默认调用的是全局的operator new函数和operator delete函数,但若是一个类重载了专属的operator new函数和operator delete函数,那么new和delete就会调用这个专属的函数。
例如:
class StackOnly
{
public:static StackOnly CreateObj(){return StackOnly();}
private:StackOnly(){}void* operator new(size_t size) = delete;void operator delete(void* p) = delete;//void* operator new(size_t size);//void operator delete(void* p);
};
但依旧无法防止在静态区拷贝构造对象。
只要子类不能调用父类的构造函数即可。
方法1:
与前面类似,将构造函数私有化,用一个静态函数返回对象即可。
方法2:
用c++11的关键字,final,表示该类不能被继承。
例如:
class A final
{// ....
};
class Singleton
{
public://3、提供一个全局访问点获取单例对象static Singleton* GetInstance(){return _inst;}
private://1、将构造函数设置为私有,并防拷贝Singleton(){}Singleton(const Singleton&) = delete;Singleton& operator=(const Singleton&) = delete;//2、提供一个指向单例对象的static指针static Singleton* _inst;
};
//在程序入口之前完成单例对象的初始化
Singleton* Singleton::_inst = new Singleton;
赋值重载是对于已经存在的对象,这里可以不做处理。
关于单例模式(饿汉实现)线程安全的问题:
饿汉模式是在程序运行主函数之前就完成了单例对象的创建,由于main函数之前是不存在多线程的,因此饿汉模式下单例对象的创建过程是线程安全的。后面访问这个对象是一个读的操作,也不会造成线程不安全。
懒汉模式:
例如:
在获取单例对象时进行加锁处理,防止多线程时创建多个对象。
class Singleton
{
public://3、提供一个全局访问点获取单例对象static Singleton* GetInstance(){//加锁if (_inst == nullptr){_inst = new Singleton;}//解锁return _inst;}
private://1、将构造函数设置为私有,并防拷贝Singleton(){}Singleton(const Singleton&) = delete;Singleton& operator=(const Singleton&) = delete;//2、提供一个指向单例对象的static指针static Singleton* _inst;
}//在程序入口之前先将static指针初始化为空
Singleton* Singleton::_inst = nullptr;
当对象被创建出来之后,只是进行读操作,没必要再加锁,改进后:当该指针不为空(对象已创建)后直接返回,没必要加锁。 static Singleton* GetInstance(){if (_inst == nullptr){//加锁if (_inst == nullptr){_inst = new Singleton;}//解锁}return _inst;}