可能出现的对象生命周期管理问题
- 对象提前析构:如果
MyClass
对象是在局部作用域创建,当局部作用域结束,对象会被析构。然而多线程环境下,其他线程可能还在使用通过getInstance
获取的引用,这就导致了悬空引用,引发未定义行为。
- 资源竞争:如果
MyClass
对象的创建涉及到资源分配(如内存、文件句柄等),多个线程同时调用getInstance
可能会导致资源竞争,出现重复分配或者分配失败等问题。
解决方法
- 使用单例模式:
- 饿汉式单例:在程序启动时就创建
MyClass
的实例,这样在多线程调用getInstance
时,实例已经存在,避免了竞争。
class MyClass {
public:
static const MyClass& getInstance() {
static MyClass instance;
return instance;
}
private:
MyClass() = default;
MyClass(const MyClass&) = delete;
MyClass& operator=(const MyClass&) = delete;
~MyClass() = default;
};
- **懒汉式单例(线程安全)**:在第一次调用`getInstance`时创建实例,并且使用互斥锁来保证线程安全。
#include <mutex>
class MyClass {
public:
static const MyClass& getInstance() {
static std::mutex mtx;
static MyClass* instance = nullptr;
std::lock_guard<std::mutex> lock(mtx);
if (instance == nullptr) {
instance = new MyClass();
}
return *instance;
}
private:
MyClass() = default;
MyClass(const MyClass&) = delete;
MyClass& operator=(const MyClass&) = delete;
~MyClass() = default;
};
- 智能指针:如果不能使用单例模式,可以使用智能指针来管理
MyClass
对象的生命周期。例如std::shared_ptr
,它会在引用计数为0时自动释放对象。
#include <memory>
class MyClass;
std::shared_ptr<MyClass> globalInstance;
class MyClass {
public:
static const MyClass& getInstance() {
static std::mutex mtx;
std::lock_guard<std::mutex> lock(mtx);
if (!globalInstance) {
globalInstance = std::make_shared<MyClass>();
}
return *globalInstance;
}
private:
MyClass() = default;
MyClass(const MyClass&) = delete;
MyClass& operator=(const MyClass&) = delete;
~MyClass() = default;
};