删除默认构造函数与不编写默认构造函数的差异探究
C++空大括号初始化的构造函数匹配规则差异解析
要理解这三种场景的差异,核心在于C++标准对**空大括号初始化(列表初始化)**的优先级规则,以及默认构造函数的存在状态对初始化逻辑的影响:
1. 显式定义默认构造函数的场景
当类显式定义了默认构造函数(同时存在initializer_list构造函数)时,执行Obj o{};会触发C++标准中[dcl.init.list]/3.2的规则:
若初始化列表为空,且类类型拥有默认构造函数,则对象被值初始化,直接调用默认构造函数。
这条规则的优先级高于initializer_list构造函数的匹配逻辑,因此空大括号会优先调用默认构造函数,而非initializer_list构造函数。
2. 不定义默认构造函数的场景
如果类只定义了initializer_list构造函数,未显式声明默认构造函数,编译器不会生成隐式默认构造函数(C++标准规定:类存在任何用户声明的构造函数时,隐式默认构造函数不会被生成)。
此时执行Obj o{};,由于类没有默认构造函数,[dcl.init.list]/3.2的规则不适用,会进入[dcl.init.list]/3.4的构造函数重载决议阶段:
- 候选构造函数只有
initializer_list构造函数; - 空的初始化列表可以被解析为空的
std::initializer_list参数,因此该构造函数可行,最终被调用。
3. 显式删除默认构造函数的场景
当显式删除默认构造函数(Obj() = delete;)时,该构造函数是已声明但不可用的状态,类仍然被视为“拥有默认构造函数”。
执行Obj o{};时,依然触发[dcl.init.list]/3.2的规则,尝试进行值初始化并调用默认构造函数,但由于该构造函数已被删除,编译器会直接抛出编译错误,不会进入initializer_list构造函数的匹配阶段。
内容的提问来源于stack exchange,提问作者Jan Hackenberg
相关产品推荐
相关产品推荐

