当前位置: 首页 > news >正文

灵光一现的问题和常见错误1

拷贝构造函数显式写,编译器还会自动生成默认构造函数吗,还有什么函数会出现这种问题

在C++中,当类显式定义某些特殊成员函数时,编译器可能不再自动生成其他相关函数。以下是详细分析:


I. 显式定义拷贝构造函数对默认构造函数的影响

规则

  • 默认行为:如果一个类没有显式声明任何构造函数,编译器会生成一个默认的无参构造函数

  • 例外情况:如果类显式声明了任何构造函数(包括拷贝构造函数),编译器不再自动生成默认构造函数

示例

class MyClass {
public:// 显式定义拷贝构造函数MyClass(const MyClass& other) { /* ... */ }
};int main() {MyClass obj1;          // 错误:默认构造函数被抑制MyClass obj2(obj1);    // 正确:调用拷贝构造函数return 0;
}

解决方法

显式定义默认构造函数:

class MyClass {
public:MyClass() = default;   // 显式要求编译器生成默认构造函数MyClass(const MyClass& other) { /* ... */ }
};

II. 其他受影响的特殊成员函数

除了默认构造函数,以下函数的自动生成规则也会受到显式定义其他函数的影响:

显式定义的函数编译器不再自动生成的函数
拷贝构造函数默认构造函数、移动构造函数、移动赋值运算符
拷贝赋值运算符移动构造函数、移动赋值运算符
移动构造函数拷贝构造函数、拷贝赋值运算符
移动赋值运算符拷贝构造函数、拷贝赋值运算符
析构函数移动构造函数、移动赋值运算符

III. 具体场景分析

(1) 显式定义拷贝构造函数

  • 抑制的自动生成函数

    • 默认构造函数(需显式定义)

    • 移动构造函数(需显式定义)

    • 移动赋值运算符(需显式定义)

(2) 显式定义析构函数

  • 抑制的自动生成函数

    • 移动构造函数(需显式定义)

    • 移动赋值运算符(需显式定义)

(3) 显式定义移动构造函数

  • 抑制的自动生成函数

    • 拷贝构造函数(需显式定义)

    • 拷贝赋值运算符(需显式定义)


IV. C++11 的改进:= default 和 = delete

为了更精细地控制编译器生成的特殊成员函数,C++11引入了显式语法:

(1) 强制生成默认函数

class MyClass {
public:MyClass() = default;                   // 强制生成默认构造函数MyClass(const MyClass&) = default;     // 强制生成拷贝构造函数MyClass(MyClass&&) = default;          // 强制生成移动构造函数
};

(2) 禁用特定函数

class NonCopyable {
public:NonCopyable() = default;NonCopyable(const NonCopyable&) = delete;  // 禁止拷贝NonCopyable& operator=(const NonCopyable&) = delete;
};

V. 总结:编译器自动生成函数的条件

特殊成员函数自动生成条件
默认构造函数没有显式声明任何构造函数
拷贝构造函数没有显式声明拷贝构造函数、移动构造函数、移动赋值运算符或析构函数
拷贝赋值运算符没有显式声明拷贝赋值运算符、移动构造函数、移动赋值运算符或析构函数
移动构造函数没有显式声明拷贝构造函数、拷贝赋值运算符、移动构造函数、移动赋值运算符或析构函数
移动赋值运算符没有显式声明拷贝构造函数、拷贝赋值运算符、移动构造函数、移动赋值运算符或析构函数
析构函数始终自动生成(除非显式声明)

VI. 最佳实践

  1. 显式定义或禁用关键函数:如果需要自定义拷贝、移动或析构逻辑,显式定义相关函数。

  2. 优先使用 = default:保留编译器生成的默认行为,避免手动实现冗余代码。

  3. 注意移动语义的兼容性:在定义拷贝操作时,考虑是否需要显式定义移动操作。

通过合理控制特殊成员函数的生成,可以避免潜在的错误,并确保类的行为符合预期。

相关文章:

  • 搭建基于Windows平台的http文件服务(miniserve+filebrowser+nssm)
  • Datawhale PyPOTS时间序列5月第3次笔记
  • 湖北理元理律师事务所:债务优化中的双维支持实践解析
  • 一分钟用 MCP 上线一个 贪吃蛇 小游戏(CodeBuddy版)
  • java中的运算符
  • 多线程(4)——线程安全,锁
  • 数学复习笔记 16
  • 在 Linux 上安装 MATLAB:完整指南与疑难解决方案
  • 交流学习 | 江西同为科技有限公司赴海尔总部考察交流
  • Spring源码之解决循环依赖 三级缓存
  • Python二进制运算:高效操作与实用技巧
  • OpenHarmony外设驱动使用 (二),Camera
  • [ctfshow web入门] web118
  • hysAnalyser 从MPEG-TS导出ES功能说明
  • Leaflet使用SVG创建动态Legend
  • wifiactivity 界面 要在哪里注册,注销广播?onResume() vs onPause() 的本质区别
  • 安装nerdctl和buildkitd脚本命令
  • LLM智能体新纪元:深入解析MCP与A2A协议,赋能智能自动化协作
  • stack和queue简单模拟实现
  • Linux面试题集合(3)
  • 倒票“黄牛”屡禁不绝怎么破?业内:强化文旅市场票务公开制度
  • 德州国资欲退出三东筑工,后者大股东系当地房企东海集团
  • 英德宣布开发射程超2000公里导弹,以防务合作加强安全、促进经济
  • 最高检公布一起离婚纠纷典型案例:推动离婚经济补偿制度落实
  • 李公明︱一周书记:当前科学观中的盲点、危机与……人类命运
  • 党建评:对违规宴饮等问题要坚决露头就打