文章目录
- 不能被拷贝
- 只在堆上创建
- 只能在栈上创建
- 不能被继承
- 饿汉单例 程序启动前就创建好
- 懒汉单例 需要的时候即调用GetInstance时再创建单例
不能被拷贝
class CopyBan
{public:CopyBan(){}private:// C++98CopyBan(const CopyBan&);CopyBan& operator=(const CopyBan&);// C++11CopyBan(const CopyBan&) = delete;CopyBan& operator=(const CopyBan&) = delete;
};
- 私有:类外无法调用 类外无法定义
- 无定义:类内即使调用也无实现
只在堆上创建
析构函数私有化 + 提供销毁接口
class HeapOnly
{public:// 提供接口销毁堆上对象void Destroy(){delete this;}private:// 析构函数私有 导致无法在栈上创建对象~HeapOnly(){cout << "~HeapOnly()" << endl;}
};
int main()
{HeapOnly* hp = new HeapOnly;hp->Destroy();return 0;
}
构造函数私有 + 提供静态成员函数
class HeapOnly
{public:static HeapOnly* CreateObj(){return new HeapOnly;}private:HeapOnly(){}HeapOnly(const HeapOnly&) = delete;HeapOnly& operator=(const HeapOnly&) = delete;
};
int main()
{HeapOnly* hp = HeapOnly::CreateObj();return 0;
}
只能在栈上创建
class StackOnly
{public:static StackOnly CreateObj(){StackOnly obj;return obj;}private:StackOnly(){}
};
int main()
{StackOnly st1 = StackOnly::CreateObj();StackOnly* st2 = new StackOnly(st1);// error 这里仍然可以调用return 0;
}
不能通过禁用拷贝构造,CreateObj()返回栈上的对象是传值返回,需要拷贝构造函数。
在类里面写一个 operator new 并禁掉。使用 new时,默认调的是全局的 new,但是如果我们在类中写一个 operator new,那么当我们 new 一个该类的对象时,会优先调用我们自己写的 operator new,所以我们只需要把自己写的 operator new 禁掉即可。
new = operator new() + 构造函数
class StackOnly
{
public:static StackOnly CreateObj(){StackOnly obj;return obj;}// 实现类专属的 operator newvoid* operator new(size_t size) = delete;
private:StackOnly(){}
};
不能被继承
// C++98
class NonInherit
{public:static NonInherit GetInstance(){return NonInherit();}private:NonInherit(){}
};// C++11
class NonInherit final
{public:NonInherit(){}private:// ...
};
饿汉单例 程序启动前就创建好
程序启动前_inst静态对象就初始化完毕 之后使用该单例时调用GetInstancePtr()即可
class Singleton
{public://static Singleton& GetInstance()//{// return inst;//}static Singleton* GetInstancePtr(){return &_inst;}private:static Singleton _inst; // 声明Singleton(){}Singleton(const Singleton&) = delete;Singleton& operator=(const Singleton&) = delete;
};// 定义
Singleton Singleton::_inst;
指针版本
class Singleton
{
public:static Singleton* GetPtrAtOnly(){return _ponly;}private:static Singleton* _ponly;Singleton() {}Singleton(const Singleton&) = delete;Singleton& operator=(const Singleton&) = delete;
};
Singleton* Singleton::_ponly = new Singleton;int main()
{Singleton* instPtr = Singleton::GetPtrAtOnly();return 0;
}
懒汉单例 需要的时候即调用GetInstance时再创建单例
class Singleton
{
public:static Singleton* GetInstance(){// error 线程不安全//if (_inst == nullptr)//{// _inst = new Singleton;//} ok but 效率低//_ptrmtx.lock();//if (_inst == nullptr)//{// _inst = new Singleton;//}//_ptrmtx.unlock(); error 相当于没加锁//if (_inst == nullptr)//{// _ptrmtx.lock();// _inst = new Singleton;// _ptrmtx.unlock();//}// okif (_inst == nullptr){_ptrmtx.lock();if (_inst == nullptr){_inst = new Singleton;}_ptrmtx.unlock();}return _inst;}
private:static Singleton* _inst;static mutex _ptrmtx;Singleton(){}Singleton(const Singleton&) = delete;Singleton& operator=(const Singleton&) = delete;
};
mutex Singleton::_ptrmtx;
Singleton* Singleton::_inst = nullptr;
C++11后支持这样写且线程安全
// 懒汉
class Singleton
{
public:static Singleton& GetInstance() {static Singleton instance; return instance;}private:Singleton() {}~Singleton() {}Singleton(const Singleton& s) = delete;Singleton& operator=(const Singleton& s) = delete;
};class Singleton2
{
public:static Singleton2* GetPtrAtOnly(){static Singleton2 one;return &one;}private:Singleton2() {}~Singleton2() {}Singleton2(const Singleton2& s) = delete;Singleton2& operator=(const Singleton2& s) = delete;
};int main()
{Singleton& singletonInstance = Singleton::GetInstance();Singleton2* instPtr = Singleton2::GetPtrAtOnly();return 0;
}