You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

带explicit默认构造函数时,空大括号拷贝列表初始化为何遭编译器拒绝?

列表初始化中explicit构造函数的编译器行为解析

一、单explicit默认构造函数的编译报错问题

先看这段代码:

struct A
{
    explicit A() {}
};

int main()
{
    A a = {};
}

所有主流编译器都会拒绝编译这段代码,核心争议点在于A a = {};的初始化规则判定:

  • 提问者认为根据标准[dcl.init.list]/3.5,该初始化属于值初始化,值初始化会直接调用默认构造函数,且默认初始化不排除explicit构造函数,理应通过编译。
  • 但编译器实际采用的逻辑是:A a = {};属于拷贝列表初始化,需执行[over.match.list]的重载决议规则——在拷贝列表初始化中,即便选中explicit构造函数,也会因规则限制导致初始化格式错误,因此编译失败。

这里的标准措辞存在一定模糊性,但主流编译器均倾向于将空列表的=初始化判定为拷贝列表初始化,而非直接触发值初始化,因此拒绝编译。

二、添加模板默认构造函数后的行为差异

修改后的代码如下:

struct A
{
    explicit A() {}

    template<typename = void>
    A() {}
};

int main()
{
    A a = {};
}

此时不同编译器出现行为分歧:

  • GCC和Clang:仍拒绝编译,错误信息显示它们依然判定这是拷贝列表初始化,重载决议中优先选择了优先级更高的非模板explicit默认构造函数,触发了拷贝列表初始化禁止选中explicit构造函数的规则。
  • EDG和MSVC:接受编译,它们的处理逻辑是在拷贝列表初始化中直接排除explicit构造函数,候选函数仅剩下非explicit的模板构造函数,因此选中该模板构造函数完成初始化。

这种差异源于编译器对“拷贝列表初始化中是否将explicit构造函数纳入候选集”的实现选择:部分编译器将其纳入候选但选中后报错,部分则直接排除explicit构造函数,仅考虑非explicit的候选。

内容的提问来源于stack exchange,提问作者user17732522

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 21:22:20