已禁用所有拷贝相关构造,为何仍能复制单例实例?
单例模式的常见误解:指针赋值≠创建新实例
你完全搞错了——SingleTone *ss = SingleTone::instance();这段代码根本没有生成第二个单例实例。它只是把指向唯一单例对象的内存地址复制给了新的指针变量ss,本质上ss和instance()返回的指针指向的是同一个对象,并不是两个独立的实例。
为什么你的类成员限制没起作用?
你删除的拷贝构造函数、赋值运算符都是针对对象本身的操作,比如禁止SingleTone s = *SingleTone::instance();这种直接拷贝对象的行为。但指针赋值是C++的基础语法,和类的特殊成员函数无关:指针只是个存储内存地址的普通变量,复制指针只是复制地址值,不会触发类的任何拷贝或赋值逻辑。
你的单例实现还有两个明显问题
- 线程不安全:
instance()里的if (singletone == nullptr)判断在多线程环境下可能被多个线程同时进入,导致多次执行new SingleTone(),最终创建多个实例,违背单例的初衷。 - 内存泄漏:你用
new创建了单例对象,但没有对应的delete操作,程序退出时这个对象不会被自动销毁,造成内存泄漏。
更可靠的单例实现方案
推荐使用C++11及以上支持的局部静态变量懒汉式,既保证线程安全,又无需手动管理内存:
class SingleTone { public: // 彻底禁止对象的拷贝、移动与赋值 SingleTone(const SingleTone&) = delete; SingleTone(SingleTone&&) = delete; SingleTone& operator=(const SingleTone&) = delete; SingleTone& operator=(SingleTone&&) = delete; // 返回引用而非指针,避免用户混淆指针赋值和对象创建 static SingleTone& instance() { // C++11标准保证局部静态变量的初始化是线程安全的 static SingleTone instance; return instance; } int get1() { return 1; } private: SingleTone() = default; };
使用时直接通过SingleTone::instance().get1()调用,或者用引用接收:SingleTone& s = SingleTone::instance();,这样就不会再产生“创建多个实例”的误解。
内容的提问来源于stack exchange,提问作者user63898
相关产品推荐
相关产品推荐

