单例模式是常用的软件设计模式,包含一个被称为单例的特殊类。通过单例模式保证系统中一个类只有一个实例(对象),而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。
定义一个单例类
因为只能有一个对象,所以在外界不能新创建对象,创建对象需要调用构造函数,可以将构造函数设为private或protected;
又因为有一个对象,将这个对象在类内部创建,用一个接口调用
因为外部无法创建对象调用,所以要设计成static类型,可以直接用类类型调用。
类用static修饰没有this指针。所以static函数不能加const修饰(const修饰this指针)
class A
{
public:
int a;
//void fun(A*const this,int x = 0 )
void fun(int x=0){a=x;}
//void fun2(A const* const this)
void fun2()const{}
}
单例模式
注意:
1.将构造函数定义private或protected
2.static成员函数不需要对象调用, 里面没有隐含的this
3.如果要求只能创建一个对象,则要将删除拷贝构造还有赋值:静态成员函数用引用返回(值返回要用拷贝构造)
方法一(懒汉模式):
class A
{
private:
static A*a;
private:
A(){};
static A& getInstance()
{
if(a==nullptr)
{
a = new A(10);
}
return a;
}
A(const A&) = delete;//删拷贝构造
public:
A& operator = (const A& a) = delete;//删赋值
}
A* A::a = nullptr;//类外初始化,使用时才初始化调用
void main()
{
A& b = A::fn();
A& bb = A::fn();//b和bb是同一个对象
// A* p = (A*)malloc(sizeof(A));
// *p = b;
}
普通懒汉式单例模式的线程不安全,可以用互斥锁改进,最好加两层锁
C++用互斥锁的方法:
#include<thread>
#include<mutex>
void* fun(void* arg)
{
mutex mtx;
mtx.lock();//加锁
mtx.unlock();//解锁
}
int main()
{
thread thr(fun);
}
方法二(饥汉模式):
class A
{
private:
static A*a;
private:
A(){};
static A& getInstance()
{
return a;
}
A(const A&) = delete;//删拷贝构造
public:
A& operator = (const A& a) = delete;//删赋值
}
A* A::a = new A;//程序一开始就创建
程序结束自动释放对象,不能提供释放的接口,否则唯一的对象都没有了。
类类型内不能出现类类型对象,否则创建该对象会无穷递归的创建它。
服务器对象可以用单例模式创建(池化技术),只有一个服务器。
多线程不安全的单例模式:
把创建对象放在接口内,可能多线程同时执行到此,产生多个对象。
class A
{
protected:
A() { cout << "A" << endl; }
A(const A&) = delete;//删拷贝构造
public:
A& operator = (const A& a) = delete;//删赋值
static A& fn()//对象调用接口
{
static A a;
return a;
}
};