c++11起支持构造函数委托,即一个构造函数通过成员初始化列表唯一调用同一类另一构造函数复用逻辑;委托时对象尚未完成构造,成员未初始化,访问未初始化成员为未定义行为;委托目标须为显式定义的构造函数,不可是带默认参数的单一构造函数;委托链禁止循环,且影响异常安全与生命周期。

构造函数委托的基本写法 C++11 起支持构造函数委托,即一个构造函数可以调用同一个类的另一个构造函数来复用初始化逻辑。关键点是:委托必须出现在成员初始化列表中,且只能作为**唯一**的初始化项(不能同时初始化其他成员或基类)。
常见错误是写成 this->ClassName(...) 或在函数体内调用,这会创建临时对象,不是委托。
正确写法如下:
class Widget {
int a, b;
public:
Widget(int x) : a(x), b(0) {}
Widget() : Widget(42) {} // ✅ 委托给含参构造函数
};
注意:Widget() 的初始化列表里只有 Widget(42),没有逗号后其他内容;否则编译报错 error: constructor delegation must be the only member initializer。
委托构造函数不能访问 this 指针所指对象的成员
委托发生时,对象尚未完成构造——内存已分配,但成员变量还未开始初始化(哪怕被委托的目标构造函数马上就要初始化它们)。因此,在被委托的构造函数体中,this 是有效的,但读写成员变量是未定义行为,如果该成员尚未被其初始化器赋值。
典型陷阱场景:
- 在被委托的构造函数体内,直接使用未出现在其初始化列表中的成员变量(比如忘了初始化
b,却在函数体里用了b++) - 委托链过长,误以为某层已“生效”,实则上层委托还没走完初始化列表
安全做法:所有成员初始化都放在初始化列表里;函数体内只做副作用小、不依赖未初始化成员的操作(如日志、断言、分配资源句柄)。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
委托与默认参数、重载构造函数的关系
委托目标必须是同一类的**另一个构造函数**,不能是带默认参数的单一构造函数“变体”。编译器不会把 Widget(int x = 42) 当作两个构造函数来看待。
例如以下写法不构成委托:
class Bad {
int x;
public:
Bad(int x = 42) : x(x) {}
Bad() { } // ❌ 这不是委托,是独立构造函数,x 未初始化!
};
而正确复用应写为:
class Good {
int x;
public:
Good(int x) : x(x) {}
Good() : Good(42) {} // ✅ 明确委托
};
另外,委托目标可以是重载的任意构造函数(只要可访问、不产生二义性),包括 explicit 构造函数——但要注意:委托本身不触发隐式转换,调用时传入的参数必须严格匹配目标构造函数签名。
委托链不能循环,且不能在初始化列表之外间接调用
编译器会在编译期检查委托链是否成环。比如 A() → B(),而 B() 又委托回 A(),会直接报错 error: delegating constructor cannot call itself(即使中间隔了一层)。
容易被忽略的坑:
- 在成员初始化列表中调用一个普通成员函数,而该函数内部又尝试构造自身对象(非委托),造成意外递归或栈溢出
- 把委托误当成“函数调用”,试图用
auto tmp = Widget(123);来中转——这生成的是临时对象,和委托无关 - 在模板类中使用委托时,若委托目标依赖模板参数推导,可能因 SFINAE 失败导致编译错误,此时需显式指定模板实参
委托的本质是“把当前对象的构造权移交给另一个构造函数”,不是语法糖,它影响对象生命周期起点和异常安全边界——一旦委托目标抛异常,当前构造函数也立即退出,且析构函数不会对已部分初始化的成员执行(除非它们已完成初始化)。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










