委托构造时用this创建对象引发未定义行为的原因及可行性探讨
问题分析与解答
一、未定义行为的成因
- 在委托构造的场景中,委托构造函数的参数计算阶段,当前类(
B)的对象还处于未完全构造的状态。 - 你的代码里,
B()委托给B(A*)时,传递的参数是new A(this)——这里的this指向的是正在构造的B实例。虽然示例中Base基类的成员似乎能正常访问,但这只是巧合:C++标准并未保证委托构造参数计算时,基类一定完成了初始化。 - 更关键的是,对象在构造完成前,不能被当作完整对象使用。此时将
this传递给A的构造函数,A在构造过程中访问Base的成员或方法,本质上是在访问一个生命周期未完全开始的对象,这种操作属于未定义行为,可能导致崩溃、异常输出或其他不可预测的结果。
二、能否在委托构造时使用当前实例(this)创建新对象?
- 绝对不可以。根据C++标准,委托构造的参数计算发生在当前对象构造的早期阶段,此时对象的生命周期尚未正式开始,
this指向的是一个不完整的对象。任何对这个this的使用(除了极少数被标准允许的场景,比如传递给基类构造函数)都会触发未定义行为,即便测试代码偶尔能运行,也只是偶然情况,不具备可靠性。
三、替代方案:无委托构造+init方法
既然委托构造的方式不可行,你可以将公共初始化逻辑提取到init方法中,通过两个独立的构造函数分别实现,既避免代码重复,又保证对象的完整性:
#include <iostream> #include <string> class Base { public: int get_int() const {return my_int;}; int my_int = 5; }; class A { public: A(Base* base = nullptr) { if(base != nullptr) { my_i = base->get_int(); } else { my_i = 42; } } int my_i; }; class B : public Base{ public: B() { init(new A(this)); } B(A* a) { init(a); } private: void init(A* a) { my_a = a; // 可在此添加更多公共初始化逻辑 } A* my_a; }; int main () { B b; std::cout << b.my_a->my_i; return 0; }
- 这种方式下,构造函数体执行时,基类
Base已经完成初始化,此时使用this是安全的——对象已进入构造函数体阶段,基类成员可正常访问,不会触发未定义行为。
内容的提问来源于stack exchange,提问作者zerocukor287
相关产品推荐
相关产品推荐

