C++中成员初始化列表与构造函数体内委托构造的差异
嘿,这个问题里其实藏着一个很容易踩的坑——你以为的两种“委托调用”,本质完全不是一回事!咱们把这俩掰扯清楚:
两种写法的核心差异
首先得明确:只有成员初始化列表里的写法,才是C++11真正支持的委托构造函数,而构造函数体内的调用完全是另一个东西:
- 初始化列表里的
Foo(int n): Foo():这是标准定义的委托构造逻辑——当前构造函数会把对象的初始化工作完全委托给无参构造Foo()。整个过程只会创建一个Foo对象:先执行无参构造完成所有成员的初始化,再执行当前构造函数体内的代码(如果有的话)。 - 构造函数体内的
Foo();:这根本不是委托!它只是在函数体里创建了一个临时的Foo对象,这个临时对象和你正在构造的对象半毛钱关系都没有。等这行代码执行完,临时对象会立刻被销毁,对你当前对象的成员变量没有任何初始化作用。你觉得“返回值一致”,大概率是因为你的无参构造没做实际的成员初始化,或者成员的默认值刚好巧合,但这绝对是错误的写法!
举个直观的例子就能看出来区别:
class Foo { public: int num; Foo() : num(10) {} // 无参构造初始化num为10 // 正确的委托构造 Foo(int n) : Foo() { num += n; // 此时num已经被无参构造初始化过,这里可以安全修改 } // 错误的写法,不是委托 Foo(double d) { Foo(); // 创建临时对象,当前对象的num还是未初始化的垃圾值 num += static_cast<int>(d); // 这里操作的是未初始化的变量,行为未定义! } };
为什么要选委托构造(初始化列表写法)
既然第二种写法是无效甚至错误的,那正确的委托构造显然是唯一选择,它的优势很明确:
- 保证初始化正确性:委托构造会确保对象的所有成员都被目标构造函数正确初始化,不会出现成员未初始化的情况(只要目标构造函数的逻辑是对的)。
- 代码复用:把多个构造函数的公共初始化逻辑集中到一个构造函数里,其他构造函数只需要委托它,避免重复写冗余代码,维护起来更方便。
- 性能更优:编译器会对委托构造做优化,不会产生额外的对象创建开销;而构造函数体内创建临时对象,平白多了一次对象的构造和销毁,完全是没必要的性能浪费。
内容的提问来源于stack exchange,提问作者W.Joe
相关产品推荐
相关产品推荐

