c++中如何定义私有构造函数_c++单例模式核心【干货】

夏敏同学_1802

夏敏同学_1802

2026-02-13

938人浏览

原创

私有构造函数需将构造函数、拷贝构造、移动构造及赋值运算符均声明为private或=delete;C++11起推荐统一用=delete确保编译期拦截。

c++中如何定义私有构造函数_c++单例模式核心【干货】

私有构造函数怎么写,为什么不能 public

私有构造函数就是把 Constructor 的访问权限设为 private,外部无法直接 new 或栈上实例化。这是单例的前提——禁止任意创建对象。

常见错误是只把构造函数设为 private,却忘了把拷贝构造、移动构造、赋值操作也禁掉,导致绕过单例约束:

  • private: 构造函数、拷贝构造函数、移动构造函数、operator=(含拷贝/移动赋值)都得显式声明为 delete 或 private
  • 否则别人用 A a = b; 或 A a(std::move(b)); 就能偷偷生成新实例
  • C++11 起推荐统一用 = delete,比仅声明 private 更安全(编译期拦截)

线程安全的单例怎么实现(懒汉式)

最常用的是“双重检查锁定”(Double-Checked Locking),但 C++11 之前有内存重排序风险;C++11 及以后靠 std::call_once + std::once_flag 更简洁可靠:

class Singleton {
private:
    Singleton() = default;
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;
    static std::unique_ptr<singleton> instance_;
    static std::once_flag init_flag_;

public:
    static Singleton& getInstance() {
        std::call_once(init_flag_, []{
            instance_ = std::make_unique<singleton>();
        });
        return *instance_;
    }
};</singleton></singleton>

注意点:

  • std::call_once 是线程安全的初始化入口,只执行一次,无需手写锁
  • std::unique_ptr 管理堆内存,避免裸指针和手动 delete
  • 不要用局部静态变量(如 static Singleton s;)实现懒汉式——它虽线程安全(C++11 要求),但销毁时机不可控,可能在其他静态对象析构后才被析构,引发 use-after-free

饿汉式单例的适用场景和隐患

饿汉式在程序启动时就构造好唯一实例,靠全局静态对象实现:

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载
class Singleton {
private:
    Singleton() = default;
    static Singleton instance_;
public:
    static Singleton& getInstance() { return instance_; }
};

优点是绝对线程安全、无延迟;但问题也很直接:

  • 实例在 main() 之前就构造,依赖的其他全局对象可能还没初始化(静态初始化顺序问题)
  • 即使从不调用 getInstance(),也会强制构造,浪费资源
  • 无法在构造函数中做运行时参数检查或抛异常(静态对象初始化阶段异常会导致程序终止)

单例类里怎么安全持有资源(如文件句柄、网络连接)

单例生命周期贯穿整个程序,资源释放必须可控且不依赖析构时机。别指望 ~Singleton() 一定被调用(比如 exit() 或 crash)。

实操建议:

  • 资源初始化放在 getInstance() 首次调用时(懒汉),而不是构造函数里
  • 提供显式 shutdown() 或 close() 方法,由主逻辑控制何时释放
  • 若必须自动清理,可用 atexit() 注册清理函数,但要确保该函数只执行一次且不抛异常
  • 避免在单例析构函数里做 I/O 或锁操作——此时其他静态对象可能已析构,容易死锁或崩溃

真正难的不是写出来,而是想清楚:这个“唯一实例”是否真的需要跨所有模块共享?有没有更松耦合的替代方案(比如依赖注入)?很多单例最后成了隐藏的全局状态,让测试和重构变困难。

C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!

相关文章

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

c++

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

2023.10.24

6244

49

Go语言中的运算符有哪些
Go语言中的运算符有哪些

Go语言中的运算符有:1、加法运算符;2、减法运算符;3、乘法运算符;4、除法运算符;5、取余运算符;6、比较运算符;7、位运算符;8、按位与运算符;9、按位或运算符;10、按位异或运算符等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.02.23

3284

5

php三元运算符用法
php三元运算符用法

本专题整合了php三元运算符相关教程,阅读专题下面的文章了解更多详细内容。

2025.10.17

1872

13

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

2025.08.29

4388

10

C++中int、float和double的区别
C++中int、float和double的区别

本专题整合了c++中int和double的区别,阅读专题下面的文章了解更多详细内容。

2025.10.23

844

4

C++ 智能指针与现代内存管理
C++ 智能指针与现代内存管理

深入讲解 C++ 现代内存管理的核心工具——智能指针,涵盖 unique_ptr 独占所有权语义、shared_ptr 引用计数机制与循环引用问题、weak_ptr 弱引用的应用场景、make_unique/make_shared 工厂函数的性能优势、自定义删除器的编写、RAII 资源管理思想的实践,以及从裸指针迁移到智能指针的重构策略,帮助开发者编写安全无泄漏的现代 C++ 代码。

2026.04.23

379

31

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

2023.07.18

6487

5

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

2023.08.10

2708

6

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

2023.07.18

6487

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习