初始化列表在构造函数体执行前完成成员初始化,避免默认构造+赋值的冗余开销,是const成员、引用及无默认构造函数类成员的唯一合法初始化方式,且按声明顺序而非列表顺序执行。

因为在构造函数体执行前完成初始化,能避免冗余操作、满足语法约束,并提升效率。
初始化列表直接构造,不走默认+赋值的弯路
对于类类型成员(如 std::string、std::vector 或自定义类),在构造函数体内用 = 赋值,实际会先调用默认构造函数创建临时对象,再调用赋值运算符覆盖。而初始化列表直接把参数传给对应构造函数,一步到位。
-
std::vector<int> data;</int>在函数体内写data = std::vector<int>(100);</int>:先构造空 vector,再分配 100 元素内存并拷贝/移动 - 在初始化列表中写
: data(100):直接构造含 100 个默认元素的 vector,仅一次内存分配 - 内置类型(如
int)无此开销,但统一用初始化列表可保持风格一致、减少认知负担
某些成员根本不能在函数体内“赋值”
const 成员、引用类型、没有默认构造函数的类成员,必须在对象诞生那一刻就完成初始化——也就是进入构造函数体之前。此时初始化列表不是优化选项,而是唯一合法途径。
-
const int x;:声明即要求初始化,函数体内x = 5;是赋值,编译失败 -
int& ref;:引用必须绑定有效对象,不能“先存在再绑定” -
NonDefault obj;(NonDefault只有带参构造函数):无法默认构造,函数体内无法凭空生成合法对象再赋值
初始化顺序由声明决定,不是按列表顺序
初始化列表里写的先后顺序不影响实际执行顺序。C++ 严格按成员在类中声明的顺序初始化,这点容易引发隐蔽 bug。
- 即使写成
: b(a + 1), a(5),若a声明在b前,仍是先初始化a,再用已初始化的a初始化b - 反过来写(
b声明在前,但列表里先写a)会导致a依赖未初始化的b,结果未定义 - 建议初始化列表项顺序与声明顺序一致,降低出错概率
它还支持更安全的资源传递
配合移动语义,初始化列表能避免不必要的拷贝。
-
Person(std::string name) : m_name(std::move(name)) { }直接将参数移入成员 - 若在函数体内写
m_name = std::move(name),则m_name先被默认构造(空字符串),再移动赋值,多一次构造开销 - 尤其对大字符串、大容器,这种差异在性能敏感场景中明显











