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
相关产品推荐
相关产品推荐

