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

C++中仅含带默认参数拷贝构造函数的类是否为LiteralType

C++字面类型与带默认参数的拷贝构造函数问题解答

结论先行

GCC和Clang的实现符合C++标准要求,MSVC的处理存在偏差。

核心规则依据

首先明确两个标准定义:

类T的拷贝构造函数是一类非模板构造函数,其首个参数为T&、const T&、volatile T&或const volatile T&,且要么无其他参数,要么其余所有参数都有默认值。

非聚合类的字面类型要求:该类型至少拥有一个非拷贝或移动构造函数的constexpr(可以是模板)构造函数。

规则推演

  1. 带默认额外参数的拷贝构造函数,本质仍属于拷贝构造函数:
    只要构造函数满足拷贝构造的定义特征,不管调用时是否传入了额外参数,它的身份始终是拷贝构造函数,不会因为调用方式的变化变成普通构造函数。
  2. 对示例中两个类的分析:
  • 类A的第二个构造函数constexpr A(const A &, int)没有给第二个参数设置默认值,不满足拷贝构造“其余所有参数都有默认值”的要求,因此它属于普通constexpr构造函数,符合字面类型的要求,所以代码可以正常编译。
  • 类B唯一的构造函数constexpr B(const B &, int = 0)完全符合拷贝构造函数的定义,属于拷贝构造函数,没有其他非拷贝/移动的constexpr构造函数,因此B不属于字面类型,不能定义constexpr修饰的B类型变量,GCC和Clang的报错符合标准要求。

关于MSVC的差异

MSVC错误地将“调用带默认额外参数的拷贝构造函数时传入额外参数”的场景,判定为调用普通构造函数,忽略了该构造函数本身的拷贝构造身份,不符合标准规定。

// 示例代码回顾
struct A {
    constexpr A(const A &) {}
    constexpr A(const A &, int) {}
};
constexpr A a{ a, 1 }; // 符合标准,编译通过

struct B {
    constexpr B(const B &, int = 0) {}
};
constexpr B b{ b, 1 }; // 不符合标准,GCC/Clang报错,MSVC错误接受

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 08:36:03