显式默认构造函数为何阻止对象按指定初始化方式构造?
显式默认构造函数为何阻止对象按指定初始化方式构造?
这个问题其实戳中了C++里explicit关键字和指定初始化器的一个容易踩的坑,我来给你掰扯清楚:
先看你给出的代码:
struct ExplicitDefaultConstructor { explicit ExplicitDefaultConstructor() {} }; struct Material { ExplicitDefaultConstructor a; int b; }; int main() { Material{.b = 2 }; }
你原本的想法是:用指定初始化器只给b赋值,编译器会自动帮我把a默认初始化好,但实际编译会直接报错——这全是explicit关键字在搞事情,核心原因有这几点:
- 当你用
.b=2这种指定初始化器创建Material对象时,对于没被显式初始化的成员a,编译器会尝试对它进行值初始化。 - 而值初始化的过程,本质是编译器在隐式语境下去调用
a的默认构造函数,但你的ExplicitDefaultConstructor默认构造函数被标记为explicit了。 - C++的规则里明明白白写着:
explicit修饰的构造函数,只能在直接初始化的场景下被调用(比如你直接写ExplicitDefaultConstructor a;或者ExplicitDefaultConstructor a{};这种显式创建对象的情况),编译器自动帮你初始化成员的行为属于隐式调用,完全不在允许范围内,所以直接被阻止了。
如果不信的话,你可以做两个测试:
- 把
explicit关键字去掉,代码就能正常编译,因为此时默认构造函数可以被隐式调用,编译器能自动完成a的初始化; - 或者在指定初始化器里显式初始化
a,比如写成Material{.a = {}, .b=2};,这属于直接初始化a,符合explicit的调用规则,也能顺利编译通过。
内容来源于stack exchange
相关产品推荐
相关产品推荐

