单例模式是一种特殊的类设计模式,要求每种类只能被创建出一个对象,饿汉模式和懒汉模式是两种解决方案
饿汉模式
首先,因为只允许创建一个对象,所以构造,拷贝,赋值都需要进行限制,私有化构造,删除拷贝和赋值
在类中声明一个全局的变量,类型为这个类本身,提供一个公有的接口,允许在main函数内调用这个接口,,在main函数之前完成对这个全局的变量的初始化
class hunger {
public:
int& GetData1() { return data1; }
int& GetData2() { return data2; }
static hunger& GetHunger() {
return _hunger;
}
private:
hunger(){}
hunger(const hunger&) = delete;
hunger operator=(const hunger&) = delete;
int data1 = 1;
int data2 = 2;
static hunger _hunger;
};
hunger hunger::_hunger;
int main() {
cout << hunger::GetHunger().GetData1() << ' ' << hunger::GetHunger().GetData2() << endl;
system("pause");
return 0;
}
饿汉模式的问题
1. 无法控制多个单例对象实例化的顺序
2. 如果单例化对象占据资源过大,会造成资源浪费
懒汉模式
构造,拷贝,赋值与饿汉类似,
饿汉模式的单例对象在main函数之前完成初始化,故无法准确预计构造的顺序,解决方案是在调用出构造,进而谁先调用,谁先构造
c++11之后
class lazy {
public:
int& GetData1() { return data1; }
int& GetData2() { return data2; }
static lazy& GetLazy() {
static lazy _lazy;
return _lazy;
}
private:
lazy() {}
lazy(const lazy&) = delete;
lazy operator=(const lazy&) = delete;
int data1 = 1;
int data2 = 2;
};
int main() {
cout << lazy::GetLazy().GetData1() << ' ' << lazy::GetLazy().GetData2() << endl;
printf("%p %p\n", &lazy::GetLazy().GetData1(), &lazy::GetLazy().GetData2());
printf("%p %p\n", &lazy::GetLazy().GetData1(), &lazy::GetLazy().GetData2());
system("pause");
return 0;
}
c++11之前(供了解)
在上面的代码中
static lazy& GetLazy() {
static lazy _lazy; // 这行代码是有线程安全问题的return _lazy;
}所以需要改成指针类型,再另加锁
class lazy {
public:
int& GetData1() { return data1; }
int& GetData2() { return data2; }
static lazy& GetLazy() {
if (_plazy == nullptr)
{
unique_lock<mutex> up(_mtx);
if (_plazy == nullptr) {
_plazy = new lazy;
}
}
return *_plazy;
}
private:
lazy() {}
lazy(const lazy&) = delete;
lazy operator=(const lazy&) = delete;
int data1 = 1;
int data2 = 2;
static lazy* _plazy;
static mutex _mtx;
};
lazy* lazy::_plazy = nullptr;
mutex lazy::_mtx;
缺点,涉及到多线程问题,代码会更复杂,效率也会低一些