会出问题。成员初始化顺序只取决于类内声明顺序,与初始化列表书写顺序无关;若依赖未初始化成员将导致未定义行为。
不会。初始化列表中成员的书写顺序,和实际初始化顺序完全无关。C++ 标准强制规定:成员变量的初始化顺序,只取决于它们在类定义中声明的先后顺序,而不是初始化列表里的顺序。
这意味着如果你在初始化列表里把 y 写在 x 前面,但 x 在类里声明在 y 之前,那么 x 依然先被初始化——哪怕它依赖 y 的值,此时 y 还没构造。
std::string 成员用另一个未初始化的 int 成员做长度参数,结果触发未定义行为buffer_size 和 data 数组)、自定义类型需显式传参构造因为 const 成员和引用成员没有“赋值”的机会——它们必须在对象诞生的那一刻就获得确定值。而构造函数体内的语句属于“赋值阶段”,此时对象已存在,const 和引用早已绑定完毕,再赋值是非法的。
例如:
class A {
c
onst int c;
int& ref;
public:
A(int x) : c(x), ref(x) {} // ✅ 正确:都在初始化列表中绑定
// A(int x) : c(x) { ref = x; } // ❌ 错误:ref 在构造函数体里无法赋值
};
const std::vector 成员试图在构造函数体里 push_back,编译失败= 赋值,可能触发默认构造 + 拷贝/移动两步,低效严格固定为四层嵌套顺序:虚基类 → 非虚基类 → 类内声明顺序的成员变量 → 构造函数体。注意:所有基类(无论是否虚)都优先于任何成员变量初始化。
例如:
struct B1 { B1() { cout << "B1 "; } };
struct B2 { B2() { cout << "B2 "; } };
struct D : B1, B2 {
int m1;
string m2;
D() : m2("hello"), m1(42) { cout << "D body"; }
}; // 输出一定是 "B1 B2 D body",m1/m2 初始化发生在 "D body" 之前,且 m1 先于 m2(因声明在前)
m2 写在 m1 前面,只要 m1 在类里声明更早,它就先初始化不安全,除非该函数是 static 的。非静态成员函数隐含访问 this,但在初始化列表执行期间,对象尚未完全构造——基类部分刚完成,成员变量可能还未初始化,此时调用非静态函数属于未定义行为。
A() : x(compute_x()) {} 中 compute_x() 是普通成员函数,内部访问了其他未初始化的成员static 成员函数、全局函数,或把逻辑移到构造函数体内(确保所依赖成员已初始化)this 后在初始化列表中调用,同样危险;捕获局部变量才安全