C++ singleton单例模式
根据C++/golang项目在对象设计需要,选择合适的设计模式。
一个单例模式(Singleton Pattern)的实现,使用了 C++11 的局部静态变量特性来确保线程安全。这段代码已经是单例模式的标准实现之一,不过有几个小问题和可以优化的地方。
代码问题分析
- 未使用的成员变量:
std::mutex m_mtx;
- 这个互斥锁在当前实现中没有被使用,因为 C++11 标准已经保证了局部静态变量的线程安全初始化,不需要额外的锁。
- 未定义的头文件:
代码包含了许多不必要的头文件,如<pthread.h>、<condition_variable>、<deque>等,这些头文件在当前代码中没有被使用。 - 私有构造函数和析构函数:
构造函数和析构函数被正确地声明为私有,但没有被显式地删除拷贝构造函数和赋值运算符,这可能导致单例被意外复制。
优化后的代码
下面是优化后的单例模式实现:
cpp
#include <iostream>
class Singleton {
public:
static Singleton* getInstance() {
static Singleton instance;
return &instance;
}
void show() const {
std::cout << "Singleton instance address: " << this << std::endl;
}
// 删除拷贝构造函数和赋值运算符,防止单例被复制
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
private:
Singleton() = default;
~Singleton() = default;
};
int main() {
Singleton::getInstance()->show();
return 0;
}
优化说明
- 移除未使用的头文件:
只保留了必要的<iostream>头文件。 - 删除拷贝构造函数和赋值运算符:
通过= delete显式禁用拷贝构造函数和赋值运算符,防止单例被复制。 - 简化构造函数和析构函数:
使用= default让编译器生成默认的构造函数和析构函数,代码更简洁。 - 改进show()方法:
将show()方法声明为const,并显示单例实例的地址,便于验证是否为同一实例。
线程安全说明
C++11 标准(§6.7 [stmt.dcl] p4)规定:
If control enters the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for completion of the initialization.
这意味着局部静态变量的初始化是线程安全的,多个线程同时访问getInstance()方法时,只有一个线程会执行初始化,其他线程会等待,直到初始化完成。因此,这种实现方式既简洁又高效,不需要额外的锁机制。