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

带转换构造函数的类型拷贝初始化失效但列表初始化有效?C++新版本是否仍如此?

问题解析:为什么B b1 = 5;会报错?

先看你给出的代码:

// C++ 14.

struct A {
    A(int i) {}
};

struct B {
    B(A a) {}
};

int main(){
    A a = 5;
    B b1 = 5; // error
    B b2 = a;
    B b3 { 5 };
    B b4 = { 5 };
    return 0;
}

报错核心原因:拷贝初始化的隐式转换限制

你观察的结论是对的,拷贝初始化(T obj = expr;形式)仅允许最多一层用户定义的隐式转换。B b1 = 5;需要两层用户定义转换才能完成:

  1. 第一步:int类型的5通过A的构造函数隐式转换为A对象(第一层用户定义转换);
  2. 第二步:A对象通过B的构造函数隐式转换为B对象(第二层用户定义转换)。

C++标准明确规定,隐式转换序列中最多只能包含一次用户定义的转换(包括构造函数转换或转换函数),因此这条语句违反规则,编译器会报错。

其他初始化语句的合法性说明:

  • A a = 5;:仅需一层用户定义转换(int→A),符合拷贝初始化规则;
  • B b2 = a;:仅需一层用户定义转换(A→B),符合拷贝初始化规则;
  • B b3 { 5 }; 和 B b4 = { 5 };:属于直接初始化/列表初始化,这类初始化会直接尝试用5作为参数调用B的构造函数,此时仅需将5转换为B构造函数要求的A类型(一层用户定义转换),因此可以正常编译。

最新C++版本中的行为

这个规则在C17、C20乃至C++23中依然存在,拷贝初始化的隐式转换序列限制未被修改。只要代码结构不变,B b1 = 5;在最新标准中仍会触发编译错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 21:55:06