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

Effective C++ 条款4:确定对象被使用前已先被初始化

Effective C++ 条款4:确定对象被使用前已先被初始化


核心思想永远在使用对象前将其初始化。未初始化对象是未定义行为的常见来源,尤其对于内置类型。

1. 内置类型手动初始化
int x = 0;                   // 手动初始化
const char* text = "Hello";   // 指针初始化
double d;                     // ❌ 危险!未初始化(值随机)

2. 类成员使用初始化列表

原因

  • 避免先默认构造再赋值的性能开销
  • const 成员和引用成员必须用初始化列表
class PhoneNumber { /*...*/ };class ABEntry {
public:ABEntry(const std::string& name, const std::string& address, const std::list<PhoneNumber>& phones);
private:std::string theName;std::string theAddress;std::list<PhoneNumber> thePhones;int numTimesConsulted;
};// ✅ 正确:初始化列表(高效且安全)
ABEntry::ABEntry(const std::string& name, const std::string& address, const std::list<PhoneNumber>& phones)
: theName(name),                 // 调用string拷贝构造函数theAddress(address),           // 同上thePhones(phones),             // 调用list拷贝构造函数numTimesConsulted(0)           // 内置类型显式初始化
{}                               // 构造函数体为空// ❌ 错误:构造函数内赋值(效率低)
ABEntry::ABEntry(...)
{ theName = name;              // 先默认构造再赋值theAddress = address;        // 额外开销!thePhones = phones;numTimesConsulted = 0;       // 此时才"初始化"
}

3. 初始化顺序规则
  • 成员初始化顺序只取决于声明顺序(与初始化列表顺序无关)
  • 始终按成员声明顺序写初始化列表
class C {int a;int b;
public:// ❌ 危险:实际初始化顺序 a(b) -> b(val)(a使用未初始化的b)C(int val) : b(val), a(b) {} // ✅ 正确:声明顺序=初始化顺序C(int val) : a(val), b(a) {} 
};

4. 静态对象初始化问题(跨编译单元)

问题:不同编译单元的全局静态对象初始化顺序不确定

// FileSystem.cpp
class FileSystem { public: int numDisks() const; };
extern FileSystem tfs;  // 全局对象// Directory.cpp
class Directory {
public:Directory() {int disks = tfs.numDisks(); // ❌ tfs可能尚未初始化}
};
Directory tempDir;      // 依赖tfs的全局对象

解决方案:使用局部静态对象(Singleton模式)

// 用函数代替直接访问全局对象
FileSystem& tfs() {static FileSystem fs;  // 首次调用时初始化return fs;
}Directory& tempDir() {static Directory td;   // 首次调用时初始化(此时tfs()已可用)return td;
}

关键原则总结

  1. 内置类型:必须手工初始化
  2. 类成员
    • 始终使用成员初始化列表
    • 初始化列表顺序与成员声明顺序一致
  3. 静态对象
    • 避免跨编译单元的初始化依赖
    • 使用"局部静态对象"模式解决初始化顺序问题

重要提醒

  • 构造函数体内赋值 ≠ 初始化(效率低且不适用于所有类型)
  • 未初始化内置类型会导致随机值(安全漏洞常见来源)
  • 静态对象初始化顺序问题可通过"首次调用时初始化"模式解决
http://www.lryc.cn/news/601011.html

相关文章:

  • 7月26日星期六今日早报简报微语报早读
  • Effective C++ 条款03:尽可能使用const
  • 【AcWing 154题解】滑动窗口
  • 【音视频协议篇】WebRTC 快速入门
  • 嵌入式硬件篇---zigbee无线串口通信问题
  • 谷歌无法安装扩展程序解决方法(也许成功)
  • 【C++】stack和queue的模拟实现
  • 机器学习的工作流程
  • 【硬件-笔试面试题】硬件/电子工程师,笔试面试题-30,(知识点:传输线特性阻抗,影响因素)
  • Avantage6.6下载与安装教程
  • 瑞吉外卖学习笔记
  • 兼容性问题记录
  • 亚马逊测评采购:如何打造安全的环境,技术基础关键
  • Python点阵字生成与优化:从基础实现到高级渲染技术
  • JavaScript 立即执行函数(IIFE)运行时行为分析笔记
  • golang实现一个规则引擎,功能包括实时增加、修改、删除规则
  • GO 从入门到精通2
  • 什么是缓存雪崩?缓存击穿?缓存穿透?分别如何解决?什么是缓存预热?
  • 编程语言Java——核心技术篇(四)集合类详解
  • 【Pandas】pandas Index objects Index.shape
  • 【595驱动8*8点阵】2022-9-11
  • Linux文件系统管理——NFS服务端的安装配置与NFS客户端的安装与挂载实操教程
  • QT核心————信号槽
  • MyBatis-Plus 进阶功能:分页插件与乐观锁的实战指南
  • org.apache.lucene.search.Query#rewrite(IndexSearcher)过时讲解
  • 框架式3D打印机结构设计cad【9张】三维图+设计说明书
  • Windows Server存储池,虚拟磁盘在系统启动后不自动连接需要手动连接
  • vulhub Earth靶场攻略
  • Java:采用mybatis+pagehealper优雅的实现分页功能
  • 文件操作认识