C++ Singleton的实现方法
一、Singleton的实现方法
Singleton模式的要求:一个系统中有且只能有一个指定类的实例
Singleton的一般实现步骤 :
- 将构造函数私有化
- 在类中指定一个静态的指向本类型 的指针变量
- 定义一个返回值为类指针的静态成员函数
代码实现
class Singleton1{
private:
Singleton1(){printf("constructor\n");}
~Singleton1(){printf("destructor\n");};
public:
static Singleton1* _instance;
static Singleton1* getInstance();
static void destory();
}
//静态对象初始化
Singleton1* Singleton1::_instance = nullptr;
//定义获取实例的函数和释放实例的函数
//风险点在于此函数是线程不安全的,存在多个线程同时进入else 循环创建实例的情况
Singleton1* Singleton1::getInstance(){
if(_instance) printf("instance already exist\n");
else _instance = new Singleton1();
return _instance;
}
void Singleton1::destory(){
if(_instance==nullptr) printf("instance already deleted\n");
else delete _instance;
}
改进方案
- 创建和删除对象指针时,存在线程不安全的情况。考虑以下改进方案
- 在初始化静态变量时,即创建实例,后续函数只能获取其值
- 对静态成员加锁
- 使用Linux pthread库中的pthread_once或C++11中的call_once,规定其执行一次
- 一开始就初始化了静态变量,造成了不必要的空间浪费。可以考虑将其定义在静态函数内部。
class Singleton1{
private:
Singleton1(){printf("constructor\n");}
~Singleton1(){printf("destructor\n");};
public:
static Singleton1* _instance;
static Singleton1* getInstance();
static void destory();
}
//静态对象初始化
Singleton1* Singleton1::_instance = nullptr;
//定义获取实例的函数和释放实例的函数
//风险点在于此函数是线程不安全的,存在多个线程同时进入else 循环创建实例的情况
Singleton1* Singleton1::getInstance(){
if(_instance) printf("instance already exist\n");
else _instance = new Singleton1();
return _instance;
}
void Singleton1::destory(){
if(_instance==nullptr) printf("instance already deleted\n");
else delete _instance;
二、定义只能在栈\堆上存在的对象
- 只能在栈空间上存在的对象,在栈上可以存在的必要条件时构造函数和析构函数不是private类型。
不能使用new 运算符创建新的类。
所以考虑重载operator new 和 operator delete 并将其作为private成员 - 只能在堆空间上存在的对象:
不能在栈上面创建,可以使用new创建
考虑将其析构函数作为private成员,此时如果在栈上创建对象,则在栈回收时就无法调用相应的析构函数,因此编译器会报错,无法通过。