带参数的构造函数需与类名同名、无返回类型;参数可设默认值;定义带参构造函数后编译器不再生成无参构造函数;同名参数须用初始化列表或this->赋值;const/引用成员必须在初始化列表中初始化;初始化顺序严格按成员声明顺序而非列表顺序。

带参数的构造函数怎么写
直接在类定义里声明构造函数名(和类名完全一致),参数列表按需添加,不需要返回类型(连 void 都不能写)。
常见错误是误加 void 或写错函数名(比如加了 constructor 后缀),编译器会当成普通成员函数,导致对象创建时参数被忽略或报错 no matching constructor。
- 参数可设默认值,例如
Person(std::string name, int age = 0),这样Person p("Alice")合法 - 如果定义了任何带参构造函数,编译器就不再自动生成无参构造函数——想同时支持
Person()和Person("Bob"),得显式写两个 - 参数名和成员变量同名时,必须用
this->name = name或初始化列表,否则赋值无效(形参覆盖了成员访问)
成员变量初始化该用初始化列表还是构造函数体
优先用初始化列表(: name(n), age(a)),尤其对 const 成员、引用成员、没有默认构造函数的类类型成员,这是唯一合法方式。
在构造函数体内用赋值(name = n;)看似等价,但实际会先调用默认构造函数初始化,再调用赋值操作符——多一次构造开销,且对某些类型根本不可行。
立即学习“C++免费学习笔记(深入)”;
- 基本类型(
int、double)二者性能无差别,但统一用初始化列表更一致 - 类类型成员:若其无默认构造函数(比如只定义了
Widget(int)),在初始化列表中不初始化就会编译失败 - 顺序以成员在类中声明的顺序为准,跟初始化列表里的书写顺序无关——这点容易引发未定义行为
const 成员和引用成员必须在初始化列表中赋值
const 成员和引用成员无法被“赋值”,只能“初始化”。一旦构造函数体开始执行,它们就已经存在且不可修改。
例如:class A { const int x; int& y; public: A(int v, int& r) : x(v), y(r) {} }; —— 如果漏掉 x(v) 或 y(r),编译直接报错 member 'A::x' must be initialized by mem-initializer。
- 即使你写
A(int v, int& r) { x = v; y = r; },编译不过,不是警告 - 引用成员绑定后不能重新绑定,所以必须在对象诞生那一刻就确定它引用谁
- 静态成员不在此列,它们不属于单个对象,不能在构造函数里初始化(得在类外定义)
初始化顺序陷阱:声明顺序决定真实顺序
初始化列表中写的顺序不影响实际调用顺序。C++ 严格按成员在类中**声明的先后顺序**进行初始化,哪怕你把后声明的成员写在初始化列表前面。
这会导致依赖关系出问题:如果 b 的初始化依赖 a 的值,但 b 在类中声明在 a 前面,那么 b 会先初始化(此时 a 还没构造),结果未定义。
- 编译器通常不会警告这种顺序不一致,只有运行时出问题才难排查
- 检查方法:把初始化列表顺序和头文件中成员声明顺序对齐,减少认知负担
- 涉及跨编译单元的全局对象时,这个规则还延伸到不同文件间的初始化顺序,更复杂









