侯捷C课程学习笔记构造函数那些事儿四
目录
侯捷C++课程学习笔记:构造函数那些事儿(四)
C++ 构造函数全面解析
上图节选自
一、构造函数基础特性
1. 核心功能定位
- 对象初始化中枢 :负责在对象创建时完成成员变量的初始化工作
- 生命周期唯一性 :每个对象在其生命周期内仅被调用一次,类似出生证明的签发过程
2. 基础语法特征
- 命名强制规范 :必须与类名完全相同,无法自定义函数名称
-
无返回值声明
:不写
void
等任何返回类型标识符
二、构造函数类型详解
1. 默认构造函数
- 无参构造规则 :当类中未显式定义任何构造函数时,编译器自动生成空实现版本
- 显式定义场景 :类包含引用成员或类成员对象没有默认构造时,必须手动定义
- 特殊初始化 :C++11支持类内成员变量直接赋默认值,与默认构造函数配合使用
2. 参数化构造函数
- 重载机制 :支持通过不同参数组合创建对象,实现多种初始化方式
-
默认参数支持
:允许参数设置默认值,如
Point(int x=0, int y=0)
-
隐式转换风险
:单参数构造函数可能导致意外类型转换,需用
explicit
关键字修饰
3. 拷贝构造函数
- 深拷贝要求 :当类包含指针或动态资源时,必须自定义拷贝构造实现深度复制
- 调用时机 :对象作为函数参数传递、函数返回对象、显式拷贝构造时触发
- 默认浅拷贝 :编译器生成的默认版本执行成员级复制,可能引发双重释放问题
4. 移动构造函数(C++11)
-
右值引用语法
:使用
&&
接收即将销毁的临时对象 - 资源转移优化 :直接接管临时对象资源,避免不必要的拷贝开销
noexcept
保证:必须声明为不抛异常,确保标准容器操作的安全性
5. 委托构造函数
- 代码复用机制 :允许构造函数调用同类其他构造,形成初始化链
- 执行顺序规则 :被委托构造先执行初始化,委托构造体后执行
- 循环检测 :编译器会阻止构造器之间的循环委托调用
6. 类型转换构造
- 单参构造特性 :支持从参数类型到类类型的隐式转换
explicit
限制:强制要求显式构造,避免意外转换导致的逻辑错误
三、特殊构造场景
1. 继承体系构造
- 基类初始化 :派生类构造函数必须通过初始化列表显式调用基类构造
- 虚继承处理 :虚基类的构造由最底层派生类直接负责初始化
2. 异常处理机制
- 资源回滚 :构造函数抛出异常时,已构造成员会自动析构
- 半成品对象 :异常导致构造中断时,不会调用对象析构函数
3. 纯虚类构造
- 抽象类支持 :即使包含纯虚函数,仍可定义构造函数完成基础初始化
- 派生类约束 :纯虚类的派生类必须实现所有纯虚函数才能实例化
四、最佳实践准则
1. 初始化列表优先
- 效率优势 :直接初始化成员变量,避免先默认构造再赋值的开销
- 强制使用场景 :常量成员、引用成员、无默认构造的类成员必须使用
2. 拷贝控制三原则
- 三位一体规则 :自定义拷贝构造时必须同时定义拷贝赋值运算符和析构函数
3. 移动语义优化
- 资源管理类必备 :对持有文件句柄、网络连接等资源的类实现移动语义
std::move
应用:明确标识可移动对象,触发移动构造/赋值
4. 构造异常安全
- 资源申请分离 :在构造完成前避免执行可能抛出异常的操作
-
智能指针辅助
:使用
unique_ptr
等管理资源,确保异常时自动释放
五、现代C++扩展
1. 聚合初始化(C++11)
- 简化结构体初始化 :允许通过花括号列表直接初始化公有成员
- 限制条件 :类没有用户声明构造、没有基类、没有虚函数
2. constexpr构造(C++11)
-
编译期构造
:声明为
constexpr
的构造函数可在编译阶段执行 - 字面值类型 :用于创建可在编译期确定值的常量表达式对象
3. 推导指引(C++17)
- 模板类支持 :指导编译器进行类模板参数推导
-
自定义规则
:通过
deduction-guide
语法指定推导逻辑
构造函数设计思维
- 最小化原则 :每个构造器只完成单一明确的初始化任务
- 防御性编程 :对输入参数进行有效性校验,特别是指针和索引值
- 文档化约束 :通过注释明确各构造器的使用场景和参数限制
- 性能可视化 :对高频使用的构造器进行性能剖析和优化
- 跨API安全 :公开接口中的类构造器需考虑二进制兼容性问题
C++构造函数全面解析
基础特性
类型详解
特殊场景
最佳实践
现代扩展
设计思维