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

C++中显式默认拷贝构造函数与未声明的区别及相关疑问

C++中显式= default与隐式合成特殊成员函数的区别

1. 拷贝构造函数的差异

先看你给出的两个类示例:

类A(无任何显式特殊成员声明)

class A{
   int x;
};

编译器会自动合成以下public成员函数:

  • 默认构造函数(A())
  • 拷贝构造函数(A(const A&))
  • 拷贝赋值运算符(A& operator=(const A&))
  • 当满足条件时(无用户声明的拷贝/移动构造、赋值,且所有成员支持移动),还会合成移动构造和移动赋值运算符。

类B(显式= default声明构造函数)

class B{
   int x;
   B() = default;
   B(const B&) = default;
};

这里存在两个关键区别:

  • 访问权限:类成员默认是private,所以显式声明的B()和B(const B&)都是private的(除非手动添加public:修饰),而类A的合成构造函数是public的。这直接导致外部无法创建B的实例或拷贝B对象,仅能在类内部或友元中调用。
  • 抑制自动生成其他特殊成员:一旦显式声明了拷贝构造函数(哪怕是= default),编译器就不会再自动合成移动构造函数和移动赋值运算符。而类A在符合条件时会自动生成这两个移动语义的函数。

2. 拷贝赋值运算符的差异

逻辑与拷贝构造函数一致:

  • 若完全不声明拷贝赋值运算符,编译器会在需要时合成public版本,且不影响移动语义函数的生成(只要其他条件满足)。
  • 若显式声明operator=(const T&) = default;:
    • 访问权限由声明位置决定(默认private)。
    • 编译器会停止自动生成移动构造和移动赋值运算符。

3. 移动构造与移动赋值运算符的差异

这两个函数的合成规则更特殊:编译器仅在无用户声明的拷贝构造、拷贝赋值、析构函数,且所有成员都支持移动时,才会自动合成它们。

  • 若完全不声明,满足条件时编译器会合成public的移动构造/赋值。
  • 若显式声明T(T&&) = default;或operator=(T&&) = default;:
    • 访问权限由声明位置决定(默认private)。
    • 显式声明移动构造/赋值不会抑制拷贝构造/赋值的自动合成,但反过来,若用户声明了拷贝构造/赋值,会直接抑制移动语义函数的生成。
    • 显式default移动构造时,如果某个成员无法移动(比如包含const成员或引用成员),编译器会将该移动构造函数定义为deleted;而隐式合成的场景下,这种情况根本不会生成移动构造函数。

核心总结

显式= default和隐式合成的核心差异集中在三点:

  • 访问权限:显式声明的函数遵循类成员默认权限规则(默认private),隐式合成的则都是public。
  • 连锁生成规则:显式声明任意一个拷贝/移动构造/赋值,都会改变编译器自动生成其他特殊成员的逻辑(最典型的是声明拷贝构造会抑制移动语义函数的生成)。
  • 移动语义的特殊处理:显式default移动函数可能生成deleted版本,而隐式合成时这类场景直接不会生成对应函数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 11:20:29