单例模式是一个类只有一个实例化对象;
为什么需要单例模式?
有的类比较复杂,频繁的创建和销毁类的对象,并且这些对象完全是可以复用的话,将会造成一些不必要的性能浪费。
单例模式包含了关于线程安全、内存模型、类加载机制等一些比较核心的知识点。
单例模式包括两种:
懒汉模式:线程不安全的;如果有两个线程s1,s2;如果正好在s1判空的位置交付了cpu的使用权,s2执行,此时s2做判断时,判空操作也是成立的,此时会new一个对象;而s2执行结束后,s1拿回cpu的使用权,而正好线程s1之前暂停的位置就是判空之后,这是会再次创建一个新的对象;
饿汉模式:线程安全的;在单例模式定义的时候就进行初始化;因为全局作用域的类成员静态变量已经初始化,所以没有多线程问题。
#include<iostream>
using namespace std;
/*
单例模式---懒汉模式;不是线程安全的
懒汉方式实现有两种:
1、静态指针+用时初始化
2、局部静态变量
*/
//静态指针+用时初始化
/*
class A {
public:
static A* getInstance();
void setup() {
cout << "inside setup" << endl;
}
private:
A() {
cout << "construct" << endl;
}
static A* aa; //定义静态指针
};
A* A::aa = nullptr;
A* A::getInstance() {
if (aa == nullptr)
aa = new A;
return aa;
}
int main() {
A* aa1 = A::getInstance();
A* aa2 = A::getInstance();
if (aa1 == aa2) cout << "Y" << endl;
else cout << "N" << endl;
cout << "Hello C++" << endl;
system("pause");
return 0;
}
*/
//局部变量的写法
/*
class A {
public:
static A& getInstance();
void setup() {
cout << "inside setup" << endl;
}
private:
A() {
cout << "inside construct" << endl;
}
};
A& A::getInstance() {
static A a;
return a;
}
int main() {
A a1 = A::getInstance();
A a2 = A::getInstance();
cout << "Hello C++" << endl;
system("pause");
return 0;
}
*/
/*
饿汉模式--线程安全的
在单例模式定义的时候就进行实例化。因为main()函数执行之前,全局作用域的类成员静态变量已经初始化,所以
没有多线程的问题;
实现方式:
1、直接定义静态对象
2、静态指针+类外初始化时new空间实现
*/
//直接定义静态对象
/*
class A {
public:
static A& getInstance();
void setup() {
cout << "inside setup" << endl;
}
private:
A() {
cout << "inside construct" << endl;
}
static A aa;
};
A A::aa; //类外定义,即main函数执行前这个对象都已经存在了,提前就创建出了对象,所以成饿汉模式
A& A::getInstance() {
return aa;
}
int main() {
A a1 = A::getInstance();
A a2 = A::getInstance();
cout << "Hello future!" << endl;
system("pause");
return 0;
}
*/
//静态指针+类外初始化的new空间实现
class A {
public:
static A* getInstace();
private:
A() {
cout << "inside construct" << endl;
}
static A* aa;
};
A* A::aa = new A; //注意这里和懒汉模式的区别;懒汉模式这里初始化的nullptr
A* A::getInstace() {
return aa;
}
int main() {
A* aa1 = A::getInstace();
A* aa2 = A::getInstace();
cout << "I am coming,C++" << endl;
system("pause");
return 0;
}