我的C++单例类返回unique_ptr报错,原因何在?
为什么返回unique_ptr的单例getInstance函数会触发编译错误?
你在实现C++单例时遇到的编译错误,核心原因是std::unique_ptr的独占所有权特性:
问题代码
#include <iostream> #include <memory> using namespace std; class Singleton { private: static unique_ptr<Singleton> obj; Singleton() { cout << "it's created!!\n"; } public: ~Singleton() { cout << "it's desctructed!!\n"; } static unique_ptr<Singleton> getInstance() { if (obj.get() == nullptr) obj.reset(new Singleton()); return obj; } }; unique_ptr<Singleton> Singleton::obj{nullptr}; int main(){ unique_ptr<Singleton> ss = Singleton::getInstance(); return 0; }
编译错误信息
/home/rt7/Desktop/ccProjects/cppTutorial/main.cc: 在静态成员函数‘static std::unique_ptr<Singleton> Singleton::getInstance()’中: /home/rt7/Desktop/ccProjects/cppTutorial/main.cc:25:16: 错误:使用了已删除的函数‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = Singleton; _Dp = std::default_delete<Singleton>]’ 25 | return obj; | ^~~ 从/usr/include/c++/11/bits/locale_conv.h:41包含的文件中, 从/usr/include/c++/11/locale:43, 从/usr/include/c++/11/iomanip:43, 从/usr/include/x86_64-linux-gnu/c++/11/bits/stdc++.h:72, 从/home/rt7/Desktop/ccProjects/cppTutorial/main.cc:1: /usr/include/c++/11/bits/unique_ptr.h:468:7: 注意:在此处声明 468 | unique_ptr(const unique_ptr&) = delete;
原因分析
std::unique_ptr是独占式智能指针,它的设计目标是保证同一时间只有一个unique_ptr持有对象的所有权。为了实现这一点,标准库显式删除了它的拷贝构造函数(就是错误信息里提到的unique_ptr(const unique_ptr&) = delete;)。
当你的getInstance函数返回类型是unique_ptr<Singleton>时,return obj;语句会尝试拷贝静态成员obj,但拷贝构造函数已经被禁用,因此编译器直接报错。
而当你把返回类型改为static unique_ptr<Singleton>& getInstance()时,返回的是obj的引用(别名),不会触发拷贝操作,所以编译可以正常通过。
正确的实现思路
单例模式的核心是全局唯一实例,所以不应该把实例的所有权转移出去。推荐的做法:
- 要么返回
unique_ptr<Singleton>&(引用),让外部使用这个引用访问实例,但注意不要让外部通过引用重置指针; - 更合理的是直接返回实例的引用,比如
static Singleton& getInstance(),内部用局部静态变量实现(更线程安全,也避免手动管理智能指针):
class Singleton { private: Singleton() { cout << "it's created!!\n"; } public: ~Singleton() { cout << "it's desctructed!!\n"; } // 禁止拷贝和移动 Singleton(const Singleton&) = delete; Singleton& operator=(const Singleton&) = delete; Singleton(Singleton&&) = delete; Singleton& operator=(Singleton&&) = delete; static Singleton& getInstance() { static Singleton instance; // 局部静态变量,第一次调用时初始化,线程安全(C++11及以上) return instance; } };
内容的提问来源于stack exchange,提问作者Osman
相关产品推荐
相关产品推荐

