从类成员返回智能指针的正确方式?Person类单例模式实现疑问
实现Person类的单例模式(C++版)
嘿,我看你已经摸到了单例模式的核心思路,但代码还没写完,而且有个容易踩的小坑,我来帮你补全并把细节说清楚,确保这个Person类真的只能生成一个实例,还能在程序任何地方安全访问。
先给你补全并修正后的代码(基础版)
首先是类的声明和实现,我调整了返回值的类型,避免unique_ptr的所有权转移问题:
头文件部分
#include <memory> class Person { // 静态成员存储唯一实例,用unique_ptr自动管理内存 static std::unique_ptr<Person> instance; // 把构造、拷贝、赋值都设为私有/禁用,确保外部不能随便创建或拷贝实例 Person() = default; Person(const Person&) = delete; Person& operator=(const Person&) = delete; ~Person() = default; public: // 返回实例的引用,避免所有权被转移 static Person& getInstance(); };
源文件实现部分
// 必须在类外初始化静态成员变量 std::unique_ptr<Person> Person::instance = nullptr; Person& Person::getInstance() { // 第一次调用时才创建实例 if (!instance) { instance = std::make_unique<Person>(); } // 返回引用,让外部能访问实例但拿不到所有权 return *instance; }
为什么要这么改?
- 不能直接返回unique_ptr:unique_ptr是独占所有权的智能指针,如果返回它,每次调用
getInstance()都会把instance的所有权转移出去,下次调用时instance就变成空指针了,会重新创建新的Person实例——这直接破坏了单例的唯一性!返回引用就不会有这个问题。 - 禁用拷贝和赋值:如果不禁用,别人可能通过拷贝构造或者赋值运算符偷偷创建新的实例,单例就白做了。
- 用unique_ptr管理内存:不用手动写delete,程序结束时会自动释放实例内存,避免内存泄漏。
更推荐的线程安全版本(C++11及以后)
上面的基础版有个问题:如果多个线程同时调用getInstance(),可能会创建多个实例(因为if (!instance)的检查不是原子操作)。C++11之后,静态局部变量的初始化是线程安全的,我们可以利用这一点写更简洁、安全的代码:
#include <memory> class Person { // 同样禁用构造、拷贝、赋值 Person() = default; Person(const Person&) = delete; Person& operator=(const Person&) = delete; ~Person() = default; public: static Person& getInstance() { // 静态局部变量,第一次调用时自动初始化,且C++11保证这个初始化过程是线程安全的 static std::unique_ptr<Person> instance = std::make_unique<Person>(); return *instance; } };
这个版本不需要在类外初始化静态成员,代码更紧凑,还天然线程安全,非常推荐。
怎么使用这个单例?
在程序任何地方,你只需要调用Person::getInstance()就能拿到唯一的Person实例,比如:
// 获取实例并调用成员方法(假设Person有sayHello方法) Person::getInstance().sayHello(); // 或者存一个引用,方便后续使用 Person& p = Person::getInstance(); p.doSomething();
内容的提问来源于stack exchange,提问作者Lion King
相关产品推荐
相关产品推荐

