C++11中无默认构造函数类对象的值初始化行为问询
关于C++11中类类型值初始化(
T()/T{})的行为解析 先把你提到的cppreference内容放出来,方便我们一起分析:
【值初始化】:
值初始化的效果为:[...]
- 若T是无默认构造函数、或拥有用户提供的默认构造函数、或拥有已删除默认构造函数的类类型,则对象被默认初始化;(C++11起)
[...]【默认初始化】:
默认初始化的效果为:
- 若T是[...]类类型,则考虑构造函数并针对空参数列表进行重载决议。选中的构造函数(为默认构造函数之一)被调用来为新对象提供初始值;
[...]
你的困惑非常合理——这段描述看起来好像有矛盾:如果类没有默认构造或者默认构造被删除,默认初始化要调用默认构造函数根本做不到啊?下面我们逐个解答你的问题:
问题1:无用户提供的默认构造函数,且类无默认构造/默认构造已删除时的情况
你的猜测完全正确——这种情况下代码根本无法通过编译。
举两个直观的例子:
// 情况1:类只有带参数的构造函数,无默认构造函数 class Foo { public: Foo(int) {} // 显式声明了带参构造,编译器不会生成隐式默认构造 }; // 情况2:主动删除默认构造函数 class Bar { public: Bar() = delete; }; int main() { Foo f{}; // 编译错误:找不到匹配的默认构造函数 Bar b{}; // 编译错误:尝试使用已删除的构造函数 'Bar::Bar()' return 0; }
核心原因是:值初始化在这个分支下会触发默认初始化,但默认初始化的前提是存在可访问、未被删除的默认构造函数——而这两种场景都不满足,所以编译器直接报错终止。
问题2:为什么要明确提及“无默认构造函数”和“已删除默认构造函数”?
这是C++标准严谨性的体现,把所有触发该值初始化分支的类类型场景都明确枚举出来,避免任何歧义:
- 无默认构造函数:比如类显式声明了其他构造函数,但没有声明默认构造函数(C++11及之后,编译器不会为显式声明了构造函数的类生成隐式默认构造);
- 已删除默认构造函数:这是C++11新增的语法,属于开发者主动禁用默认构造的场景,和“被动没有默认构造”是完全不同的情况;
- 拥有用户提供的默认构造函数:这是该分支里唯一能正常编译执行的子情况——此时默认初始化会调用用户写的默认构造函数。
把这三种情况并列,是为了完整覆盖所有无法触发值初始化“零初始化”分支的类类型:只有当类拥有未删除、非用户提供的默认构造函数时,值初始化才会先把所有成员置零,再调用隐式默认构造;其他所有类类型场景,都走“默认初始化”这个分支。
另外补充你提到的细节:你对用户提供默认构造函数的行为理解是对的——此时默认初始化只会执行构造函数里显式写的逻辑,未显式初始化的成员会被默认初始化(比如内置类型成员会变成未定义值,类类型成员会递归执行默认初始化)。
内容的提问来源于stack exchange,提问作者KiraMichiru
相关产品推荐
相关产品推荐

