实现方式:
class HeapOnly
{
public:
static HeapOnly* GetObject()
{
return new HeapOnly;
}
private:
HeapOnly()
{}
//HeapOnly(const HeapOnly &hp)//只声明,不实现
HeapOnly(const HeapOnly& hp) = delete;//直接删除
};
void test()
{
HeapOnly* hp = HeapOnly::GetObject();
HeapOnly copy(*hp);//可能会进行拷贝,所以禁止掉拷贝构造
}
方法一:同上将构造函数私有化,然后设计静态方法创建对象返回即可。
class StackOnly
{
public:
static StackOnly GetObject()
{
return StackOnly();//构造一个匿名对象,拷贝返回即可
}
private:
StackOnly()
{}
};
void test()
{
StackOnly sk = StackOnly::GetObject();
}
方法二:屏蔽new,因为new在底层调用void * operator new(size_t size)函数,只需将该函数屏蔽掉即可。
但是这种方法是有缺陷的,屏蔽了operator new ,不能在堆上创建空间,但是防止不了在全局区和静态区创建对象(static),所以还是建议使用方法1。
class StackOnly
{
public:
StackOnly()
{}
//operator new是库函数,和malloc用法是一样的
void* operator new(size_t size) = delete;
};
void test()
{
StackOnly sk;
}
拷贝只会放生在两个场景中:拷贝构造函数以及赋值运算符重载,因此想要让一个类禁止拷贝,只需让该类不能调用拷贝构造函数以及赋值运算符重载即可。
class NoCopy
{
public:
NoCopy()
{}
private:
NoCopy(const NoCopy& nc);
NoCopy& operator = (NoCopy& nc);
};
原因:
class NoCopy
{
public:
NoCopy()
{}
NoCopy(const NoCopy& nc) = delete;
NoCopy& operator = (NoCopy& nc) = delete;
};
class parent
{
private:
parent()
{};
};
class child:public parent
{
child()
{}
};
class parent final //final修饰,不能被继承
{
public:
parent()
{};
};
class child:public parent
{
child()
{}
};
单例模式:
一个类只能在全局(进程中)创建一个实例对象,即单例模式,该模式可以保证系统中该类只有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息,这种方式简化了在复杂环境下的配置管理。
单例模式有两种实现模式:
不管将来用不用,程序启动时就创建一个唯一的实例对象。
如果这个单例对象在多线程高并发环境下频繁使用,性能要求较高,那么显然使用饿汉模式来避免资源竞争,提高响应速度更好。
// 饿汉模式
class Singleton
{
public:
static Singleton* GetInstance()
{
return &_instance;
}
private:
// 构造函数私有
Singleton() {};
// C++11
Singleton(Singleton const&) = delete;
Singleton& operator=(Singleton const&) = delete;
static Singleton _instance;
};
// static对象在main函数之前创建,此时只有主线程,所以不存在线程安全的问题
Singleton Singleton::_instance;
饿汉模式的特点:
饿汉模式的优缺点:
如果这个单例对象在多线程高并发环境下频繁使用,性能要求较高,那么显然使用饿汉模式来避免资源竞争,提高响应速度更好。
如果单例对象构造十分耗时或者占用很多资源,比如加载插件, 初始化网络连接,读取文件啊等等,而有可能该对象程序运行时不会用到,那么也要在程序一开始就进行初始化,就会导致程序启动时非常的缓慢。 所以这种情况使用懒汉模式(延迟加载)更好。
//懒汉模式
class Singleton
{
public:
static Singleton* GetInstance()//返回指针
{
if (_ptr == nullptr)//双检查,防止多次加锁进行无关消耗
{
//初始化一次
unique_lock<mutex> lock(_mtx);//防止临界资源不安全,进行加锁
if (_ptr == nullptr)
{
_ptr = new Singleton;
}
}
return _ptr;
}
//主动释放
static void DelInstance()
{
if (_ptr)
{
unique_lock<mutex> lock(_mtx);
delete _ptr;
_ptr = nullptr;
}
}
// 实现一个内嵌内部类垃圾回收类
class CGarbo //程序结束了,资源自然会还给系统,可写可不可
{
public:
~CGarbo()
{
Singleton::DelInstance();
}
};
private:
Singleton()
{};
//拷贝、赋值需要禁掉
Singleton(const Singleton& s) = delete;
Singleton& operator=(const Singleton& s) = delete;
static Singleton* _ptr;
static mutex _mtx;
// 声明一个静态成员变量,程序结束时,系统会自动调用它的析构函数从而释放单例对象
static CGarbo _cg;
};
Singleton* Singleton::_ptr = nullptr;//初始化为空
mutex Singleton::_mtx;//初始化锁
Singleton::CGarbo Singleton::_cg;//初始化
懒汉模式的特点:
懒汉模式的优缺点: