C++构造函数内显式构造类成员时是否会调用默认构造函数
C++ 构造时序相关问题解答
你提供的示例代码如下:
class MyClass{ public: MyClass(){ // do other stuff *oc = OtherClass(params); } private: OtherClass* oc; }
针对你的几个疑问,逐一解答如下:
构造函数调用时序说明
- 执行到构造函数内
// do other stuff代码段时,不存在任何已构造的OtherClass对象,你猜测的“初始化阶段先调用OtherClass默认构造、进入构造函数后再重新赋值”的情况完全不会发生。 - 原因很简单:
oc是指针类型的成员变量,属于内置类型,如果你没有在构造函数初始化列表里给它显式赋值,进入构造函数体时它的值是随机的野指针,没有指向任何合法的OtherClass实例,自然不会触发OtherClass的任何构造逻辑。 - 代码里
*oc = OtherClass(params);这一行确实会调用OtherClass的带参构造,生成一个临时的OtherClass对象,但紧接着你解引用了野指针,尝试把临时对象赋值给野指针指向的非法内存地址——这是典型的未定义行为,运行时大概率直接崩溃,根本不是给合法存在的对象重新赋值。
OtherClass无默认构造时的表现
- 就你贴的这段错误代码而言,不会触发编译错误:因为你全程没有在合法内存位置构造OtherClass对象,编译器不会检查你对OtherClass构造函数的调用。但代码运行时必然触发内存错误,没有实际可运行性。
- 如果你本来想写的成员是对象实例而非指针(即
OtherClass oc;),又没有在构造函数初始化列表里显式调用OtherClass的带参构造,编译器才会报编译错误:它会在成员初始化阶段尝试调用OtherClass的默认构造,找不到对应实现就会终止编译。 - 如果你确实需要用指针持有OtherClass实例,正确写法是在构造函数初始化列表里给指针分配合法内存,比如
MyClass() : oc(new OtherClass(params)) { /* do other stuff */ },这种场景下哪怕OtherClass没有默认构造,只要传入参数匹配带参构造的签名,就能正常编译运行。
成员定义处直接构造对象的实践建议
- 对于非指针类型的对象成员,C++11及之后的标准支持在成员声明时直接写初始化逻辑,比如
OtherClass oc{params};,这是被广泛认可的良好实践:如果类的多个构造函数都需要用相同参数初始化这个成员,这种写法可以减少初始化列表的重复代码,也能避免成员遗漏初始化的问题。 - 对于裸指针类型的成员,绝对不要在声明处直接写
new OtherClass(params)初始化:裸指针需要手动管理内存释放,非常容易引发内存泄漏、重复释放的问题。如果需要指针语义的成员,优先使用std::unique_ptr、std::shared_ptr这类智能指针,在声明处或者构造函数初始化列表里构造即可,生命周期会被自动管理。 - 额外提示:你当前示例里解引用未初始化指针的写法是严重错误,任何生产场景下都不能这么写,指针解引用前必须确保它指向已经合法分配的内存。
内容的提问来源于stack exchange,提问作者user16541120
相关产品推荐
相关产品推荐

