cen's blog cen's blog
首页
  • 编程文章

    • markdown使用
  • 学习笔记

    • 《JavaScript教程》
    • C++学习
    • C++数据结构
    • MySQL
    • Linux
  • 高中时代
  • 工作日常
  • CLion
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 分类
  • 标签
  • 归档
关于
GitHub (opens new window)

cen

十年饮冰,难凉热血
首页
  • 编程文章

    • markdown使用
  • 学习笔记

    • 《JavaScript教程》
    • C++学习
    • C++数据结构
    • MySQL
    • Linux
  • 高中时代
  • 工作日常
  • CLion
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 分类
  • 标签
  • 归档
关于
GitHub (opens new window)
  • 类和对象
  • 内存管理
  • 泛型模板
  • string
  • vector
  • list
  • stack和queue
  • priority_queue
  • 继承
  • 多态
  • set和map
  • bitset
  • C++11
  • 异常
  • 智能指针
  • 特殊类设计
    • 只能在堆上创建对象的类
    • 只能在栈上创建对象的类
    • 单例模式
      • 饿汉模式
    • 懒汉模式
  • 线程库
  • C++学习笔记
cen
2025-02-06
目录

特殊类设计

# 只能在堆上创建对象的类

只能在堆上创建对象,也就是只能通过new操作符创建对象,方式如下:

  • 将构造函数设置为私有,防止外部直接调用构造函数在栈上创建对象。
  • 向外部提供一个获取对象的static接口,该接口在堆上创建一个对象并返回。
  • 将拷贝构造函数设置为私有,并且只声明不实现,防止外部调用拷贝构造函数在栈上创建对象。
class HeapOnly {
public:
    static unique_ptr<HeapOnly> CreateObj() {
        return unique_ptr<HeapOnly>(new HeapOnly());
    }

    HeapOnly(const HeapOnly &hp) = delete;

    HeapOnly &operator=(const HeapOnly &hp) = delete;

private:
    HeapOnly() = default;
};
1
2
3
4
5
6
7
8
9
10
11
12
13

# 只能在栈上创建对象的类

  • 将构造函数设置为私有,防止外部直接调用构造函数在堆上创建对象。
  • 向外部提供一个获取对象的static接口,该接口在栈上创建一个对象并返回。
  • 屏蔽operator new函数和operator delete函数。
class StackOnly {
public:
    static StackOnly CreateObj() {
        return StackOnly();
    }

private:

    StackOnly() {}

    void *operator new(size_t size) = delete;

    void operator delete(void *p) = delete;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 单例模式

单例模式指的就是一个类只能创建一个对象,该模式可以保证系统中该类只有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。

# 饿汉模式

如果这个单例对象在多线程高并发环境下频繁使用,性能要求较高,那么显然使用饿汉模式来避免资源竞 争,提高响应速度更好。

  • 将构造函数设置为私有,并将拷贝构造函数和赋值运算符重载函数设置为私有或删除,防止外部创建或拷贝对象。
  • 提供一个指向单例对象的static指针,并在程序入口之前完成单例对象的初始化。
  • 提供一个全局访问点获取单例对象。
// 饿汉模式
// 优点:简单
// 缺点:可能会导致进程启动慢,且如果有多个单例类对象实例启动顺序不确定。
class Singleton {
public:
    static Singleton *GetInstance() {
        return &m_instance;
    }

private:
    // 构造函数私有
    Singleton() {};

    // C++11
    Singleton(Singleton const &) = delete;

    Singleton &operator=(Singleton const &) = delete;

    static Singleton m_instance;
};

Singleton Singleton::m_instance; // 在程序入口之前就完成单例对象的初始化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 懒汉模式

如果单例对象构造十分耗时或者占用很多资源,比如加载插件啊, 初始化网络连接啊,读取文件啊等 等,而有可能该对象程序运行时不会用到,那么也要在程序一开始就进行初始化,就会导致程序启动时 非常的缓慢。 所以这种情况使用懒汉模式(延迟加载)更好。

  • 将构造函数设置为私有,并将拷贝构造函数和赋值运算符重载函数设置为私有或删除,防止外部创建或拷贝对象。
  • 提供一个指向单例对象的static指针,并在程序入口之前先将其初始化为空。
  • 提供一个全局访问点获取单例对象。
// 懒汉模式
// 优点:第一次使用实例对象时,创建对象。进程启动无负载。多个单例实例启动顺序自由控制。
// 缺点:复杂

#include <iostream>
#include <mutex>
#include <thread>
using namespace std;

class Singleton {
public:
    static Singleton *GetInstance() {
        // 注意这里一定要使用Double-Check的方式加锁,才能保证效率和线程安全
        if (nullptr == m_pInstance) {
            m_mtx.lock();
            if (nullptr == m_pInstance) {
                m_pInstance = new Singleton();
            }
            m_mtx.unlock();
        }
        return m_pInstance;
    }

    // 实现一个内嵌垃圾回收类 
    class CGarbo {
    public:
        ~CGarbo() {
            if (Singleton::m_pInstance)
                delete Singleton::m_pInstance;
        }
    };

    // 定义一个静态成员变量,程序结束时,系统会自动调用它的析构函数从而释放单例对象
    static CGarbo Garbo;
private:
    // 构造函数私有
    Singleton() {};

    // 防拷贝
    Singleton(Singleton const &);

    Singleton &operator=(Singleton const &);

    static Singleton *m_pInstance; // 单例对象指针
    static mutex m_mtx; //互斥锁
};

Singleton *Singleton::m_pInstance = nullptr;
Singleton::CGarbo Garbo;
mutex Singleton::m_mtx;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
上次更新: 2025/02/07, 18:31:39
智能指针
线程库

← 智能指针 线程库→

最近更新
01
线程安全
05-21
02
cmake教程
05-08
03
项目
05-07
更多文章>
Theme by Vdoing | Copyright © 2024-2025 京ICP备2020044002号-3 京公网安备11010502056119号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式