特殊类定制
在C++中,一些特殊性质的类如何设计
类禁止拷贝的对象
- C++11 使用delete关键字赋值给拷贝构造和赋值
- C++98将拷贝构造和赋值声明在私有里
类只能在堆上创建的对象
- 将构造函数私有化, 提供一个获取对象堆上创建对象的公有函数
- 将析构函数私有化, 提供一个释放资源公有函数
类只能在栈上创建的对象
- 将构造函数私有化, 并提供一个获取栈上创建的对象的公有函数
然后将operator new函数禁用掉, 但是无法防拷贝(有一定缺陷)
不能被继承的类
- C++98将父类构造函数私有化
- C++11使用final关键字修饰父类
单例模式
一个类只能创建一个对象的类(singleton)
即只有唯一的实例对象
-
饿汉模式: 无论是否使用, 程序创建之前(main函数之前)就构造一个唯一的对象
- 先将构造函数私有化
- 使用私有的一个静态的、对应类型的实例化对象成员, 在类内声明, 类外初始化
- 提供一个静态成员函数获取到该对象
- 优点: 简单, 无线程安全问题
- 缺点
- 单例模式多可能会导致进程的启动慢
- 一个程序中, 有多个单例时, 无法控制其初始化的顺序
-
懒汉模式: 第一次使用对象时再创建实例对象
-
设计方式同饿汉基本相同, 但调用静态成员函数时(需要获取实例对象时)再创建实例对象(new 实例对象)
-
优点对应着饿汉的缺点
- 可以控制多个单例的初始化顺序
- 不影响启动顺序
-
缺点
-
线程安全问题
- 需要通过对应加锁, 以及双重判断进行保护
static ThreadPool<T> *getIntance(int num = g_thread_num){// 双重判断, 减少反复的加锁和解锁操作(因为只有第一次调用该方法时才会有线程安全问题, 之后都不会)// 加多一个判断, 后续再来的线程时, 则不需要再进行加解锁, 只用做一次判断即可(拦截了大量的无用的访问锁的行为->只有第一次访问锁有意义)if (pool == nullptr){LockGuard lock(&_smtx);if (pool == nullptr){pool = new ThreadPool<T>(num);}}return pool; }
-
-
-
单例对象的释放问题
- 一般情况下, 单例对象在整个程序运行期间都需要使用, 所以一般都是不释放的
单例对象在进程结束后也会进行资源释放 - 一些特殊场景需要释放, 如单例对象析构时, 需要进行一些持久化操作(往文件或者数据库写)
构建一个内嵌的垃圾回收类, 然后声明一个全局的垃圾回收对象, 当单例对象生命周期到时, 则会自动析构该垃圾对象, 同时释放单例对象资源
- 一般情况下, 单例对象在整个程序运行期间都需要使用, 所以一般都是不释放的