当前位置: 首页 > news >正文

11.什么是单例模式?

11.什么是单例模式?

1.确保一个类只有一个实例,并提供一个全局访问点来获取这个实例。

2.什么时候使用单例
  核心思想:系统只需要1个实例,如日志打印,

3.在单例模式下,怎么防止在堆上创建多个对象?
回答模板:

  1. 构造函数私有化:阻止外部直接 new 对象

  2. 禁用拷贝和移动构造:防止通过已有对象复制

  3. 删除 operator new:阻止通过 new 表达式在堆上分配

  4. 删除 placement new:防止在已有内存上重新构造

防御措施 防止的操作 代码实现
私有构造函数 new Singleton() private: Singleton(){}
delete 拷贝构造 Singleton s2 = s1 Singleton(const Singleton&)=delete
delete operator new new Singleton() void* operator new(std::size_t)=delete
delete placement new new(buffer) Singleton() void* operator new(std::size_t, void*)=delete


  1.私有化构造函数

class Singleton {
private:// 私有构造函数 - 阻止外部直接 newSingleton() {}// 禁止拷贝和赋值Singleton(const Singleton&) = delete;Singleton& operator=(const Singleton&) = delete;public:static Singleton& getInstance() {static Singleton instance;return instance;}
};// ❌ 以下都无法通过编译
Singleton* s1 = new Singleton();     // 错误:构造函数是私有的
Singleton s2;                        // 错误:构造函数是私有的
Singleton s3 = *s1;                  // 错误:拷贝构造函数被删除

以上属于普通防御,但这还不够! 面试官可能追问:"如果用户用 placement new 在已有内存上构造呢?"

// 重载 placement new,但标记为删除static void* operator new(std::size_t size) = delete;static void* operator new(std::size_t size, void* ptr) = delete;

 简述完整防止在堆上创建多个对象的方案?

class Singleton {
private:// 1. 私有化构造函数和析构函数Singleton() { std::cout << "Singleton created" << std::endl;}~Singleton() {std::cout << "Singleton destroyed" << std::endl;}// 2. 禁止拷贝和移动Singleton(const Singleton&) = delete;Singleton& operator=(const Singleton&) = delete;Singleton(Singleton&&) = delete;Singleton& operator=(Singleton&&) = delete;// 3. 禁止在堆上分配 - 重载 operator newstatic void* operator new(std::size_t size) = delete;static void operator delete(void* ptr) = delete;// 4. 禁止 placement newstatic void* operator new(std::size_t size, void* ptr) = delete;public:// 唯一获取实例的方法static Singleton& getInstance() {static Singleton instance;return instance;}// 如果需要,提供一个方法来安全销毁(通常不需要)static void destroy() {// 注意:不能直接 delete this// Meyers Singleton 会在程序结束时自动析构}void doSomething() {std::cout << "Doing something at address: " << this << std::endl;}
};// 测试
int main() {// ✅ 正确用法Singleton& s1 = Singleton::getInstance();Singleton& s2 = Singleton::getInstance();s1.doSomething();// ❌ 以下所有操作都无法编译// Singleton s3;                           // 构造函数私有// Singleton* s4 = new Singleton();        // operator new 被删除// Singleton s5 = s1;                      // 拷贝构造被删除// Singleton* s6 = new(&s1) Singleton();   // placement new 被删除std::cout << "Same instance? " << (&s1 == &s2) << std::endl;  // truereturn 0;
}

 最后可能会问,如果用户malloc分配内存然后强制转换呢?

// 理论上可以绕过,但会导致未定义行为
void* mem = malloc(sizeof(Singleton));
Singleton* evil = reinterpret_cast<Singleton*>(mem);  // ❌ 危险!
// 构造函数没有被调用,对象状态无效

无法完全防止恶意绕过,但这不是常规用法,C++ 的类型系统已经足够安全。如果真的需要防止,可以在构造函数中检查是否已有实例:

http://www.zskr.cn/news/1491818.html

相关文章:

  • 南充黄金回收哪家靠谱 本地靠谱实体门店汇总 - 润富黄金回收
  • Web 编程核心思路 + 实用技巧(全栈通用)
  • 2026工控机应用白皮书网络安全领域深度剖析:嵌入式工控机/工业平板电脑/工业计算机厂家/全国产化主板/国产化电脑定制/选择指南 - 优质品牌商家
  • 越南服务器 ping 值多少?
  • 本科生毕业设计专用:OpenCV图像处理+CNN车牌字符识别完整实现包
  • 从PLC到储能系统,工业网络为何越来越重视自主可控?
  • 运城市黄金回收+白银回收+铂金回收+彩金回推荐收门店 本地靠谱店铺指南及地联系方式址和 - 大熊猫898989
  • 青岛家政保姆怎么选?老牌机构刘大姐家政深度测评(避坑干货)
  • 实测以Claude code+ChatGPT5.5的思路----万字黑马点评项目完整复盘
  • 铜川卖黄金选哪家 正规黄金回收门店实测汇总 - 润富黄金回收
  • Mac上跑SQL Server?用Docker搞定2019版,再教你用免费DBeaver连上它
  • 枣庄市黄金回收+白银回收+铂金回收+彩金回推荐收门店 本地靠谱店铺指南及地联系方式址和 - 大熊猫898989
  • Horizon环境下RDS应用程序池发布与管理实战:从单应用到批量授权
  • SPD矩阵与EEG分类的几何特性及Transformer应用
  • 嵌入式Linux下CANopen移植避坑指南:从定时器精度到SDO通信的实战调优
  • 《PE不饱和聚酯漆的特点与适用范围详解》
  • BentoML vs FastAPI:模型服务化中的角色定位与协同实践
  • 蓝桥杯嵌入式省赛复盘:第九届赛题里那些新手容易踩的EEPROM和长短按按键的坑
  • VCS仿真时FSDB文件生成失败?盘点$fsdbDumpvars的那些坑与正确姿势
  • SpringBoot项目快速接入讯飞语音听写,支持实时麦克风与WAV音频转中文文本
  • 计算机毕业设计之基于Hadoop1688平台数据的分析与可视化
  • RK3588 Android12开发:如何高效管理自定义分支并与官方SDK同步(避坑指南)
  • 【LeetCode刷题日记】78.子集
  • 告别C盘爆满!手把手教你将Qt5.12.6完整安装到D盘(Win10环境,含环境变量检查)
  • 2026降AIGC软件实测:10款软件对比,学术合规技巧盘点
  • 从Euromap 63文件传输到OPC UA实时数据流:一个驱动组件如何简化注塑机IIoT架构?
  • PCIe 4.0实战避坑指南:从带宽计算到信号完整性,硬件工程师必须搞懂的几个关键点
  • 2026淮安代理记账收费标准最新整理,淮安老板看这篇不花冤枉钱 - 淮安财税咨询
  • EarlyStopping救了我的GPU:一个Kaggle竞赛中的真实省时故事
  • 别再为TC37X头疼了!手把手教你用UDE Memtool 2021搞定英飞凌AURIX程序烧录