讲师中心 微信公众号

工具推荐

视频效率加速
AniShort
AniShort

AI短剧协同制作平台

Laper
Laper

剧本策划到成片协作

updream

一键生成高质量推广成片

剧云
剧云

中文短剧剧本制作平台

C++ 怎么实现深拷贝 C++ 拷贝构造与赋值运算符重写【核心】

云强姑娘_8839

云强姑娘_8839

发布时间:2026-02-02 15:35:08

|

378人浏览过

|

来源于php中文网

原创

不是必须手动实现深拷贝,但含裸指针等非RAII资源时默认浅拷贝会导致double-free;std::string/vector等已内置深拷贝;赋值运算符推荐复制-交换法,避免自我赋值问题。

c++ 怎么实现深拷贝 c++ 拷贝构造与赋值运算符重写【核心】

拷贝构造函数必须手动实现深拷贝吗

不是“必须”,但只要类里有指针成员(尤其是指向堆内存的 int*、char* 或 std::vector 以外的自定义资源),默认拷贝构造函数只会做浅拷贝——两个对象共享同一块内存,后续析构时会 double-free,程序大概率崩溃。

典型错误现象:double free or corruption、Segmentation fault (core dumped),尤其在函数返回局部对象或容器扩容时高频触发。

  • 如果所有成员都是栈对象或标准智能指针(如 std::unique_ptr),编译器生成的拷贝构造函数已自动完成深拷贝语义
  • 如果含裸指针、文件句柄、socket 描述符等非 RAII 资源,必须手动实现
  • 注意:std::string 和 std::vector 自身已管理堆内存,它们的拷贝是深拷贝,无需额外处理

赋值运算符重载的正确写法(含自我赋值保护)

赋值运算符比拷贝构造更易出错:它要先释放旧资源,再复制新资源。若没处理自我赋值(a = a),释放后就访问了野指针。

推荐采用「复制-交换」(copy-and-swap)惯用法,天然规避自我赋值和异常安全问题:

立即学习“C++免费学习笔记(深入)”;

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载
class MyClass {
    int* data_;
public:
    MyClass& operator=(MyClass other) { // 注意:参数按值传递(触发拷贝构造)
        swap(*this, other); // 交换 this 和 other 的资源
        return *this;
    }
    friend void swap(MyClass& a, MyClass& b) noexcept {
        using std::swap;
        swap(a.data_, b.data_);
    }
};
  • 不要写 if (this == &other) return *this; —— 这只是补救,掩盖了设计缺陷
  • 参数必须是值传递(MyClass other),不是 const MyClass&,否则无法移动/交换
  • 交换函数需声明为 friend 并标记 noexcept,确保 std::swap 可调用

拷贝构造函数里最容易漏掉的三件事

即使写了拷贝构造,仍常因细节导致未定义行为:

  • 忘了为新分配的内存初始化内容(比如 new int[size] 不等于 new int[size](),后者才零初始化)
  • 拷贝长度信息不一致:比如只拷了 size_,但没按它来分配/复制实际数据,或没更新 capacity_
  • 异常安全性缺失:若在拷贝中途(如 new 失败)抛出异常,当前对象可能处于半构造状态——建议在构造函数体外用 try/catch 或直接使用 std::vector 替代裸数组

示例错误写法:data_ = new int[other.size_]; memcpy(data_, other.data_, other.size_ * sizeof(int)); —— 如果 other.data_ 是 nullptr 就崩了;正确做法应先判空。

现代 C++ 中哪些情况可以彻底避开手写拷贝控制

如果你能控制类的设计,优先用 RAII 和标准类型封装资源,就能让编译器替你干活:

  • 用 std::unique_ptr<t></t> 替代 T* 数组:移动语义可用,拷贝被禁用(符合语义)
  • 用 std::shared_ptr 管理共享资源:拷贝即增加引用计数,天然线程安全
  • 用 std::string_view 替代 const char* 参数:避免所有权争议
  • 把裸资源封装进独立的小类(如 FileHandle),并在其内部实现正确的拷贝/移动逻辑,主类只需依赖它

手写拷贝构造和赋值运算符不是“高级技巧”,而是资源管理失控的信号灯。真正难的不是语法,是判断“这个类是否该支持拷贝”——很多场景下,删掉拷贝函数、只留移动,反而更清晰、更安全。

热门AI工具

更多
Atoms
Atoms Hot

Atoms是一款AI智能体工具,第一支自动构建真实业务的 AI 团队。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

立刻MV
立刻MV Hot

立刻MV是一款AI文本写作工具,AI 音乐视频(MV)创作工具。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

创客贴AI

创客贴AI是一款AI图像与设计工具,AI辅助的智能在线设计工具。

讯飞智作

讯飞智作是一款AI视频创作工具,AI文本配音工具,数字人课程、营销视频制作。

花生AI
花生AI Hot

一款AI视频创作工具,主要用于B站推出的AI视频创作工具,适合需要提升相关任务效率的用户。

PixPix
PixPix Hot

PixPix是一款面向电商视觉生产的AI商品图生成工具。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

7339

2023.08.02

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

6344

2023.10.24

Go语言中的运算符有哪些
Go语言中的运算符有哪些

Go语言中的运算符有:1、加法运算符;2、减法运算符;3、乘法运算符;4、除法运算符;5、取余运算符;6、比较运算符;7、位运算符;8、按位与运算符;9、按位或运算符;10、按位异或运算符等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

3424

2024.02.23

php三元运算符用法
php三元运算符用法

本专题整合了php三元运算符相关教程,阅读专题下面的文章了解更多详细内容。

1912

2025.10.17

c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

2418

2023.09.20

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

7339

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

3485

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

4588

2025.08.29

Postman身份认证怎么配置
Postman身份认证怎么配置

本专题从实际API接口调试场景出发,讲解Postman身份认证的完整配置流程,包括常见认证协议介绍、授权参数设置、访问令牌填写、OAuth 2.0授权及认证失败排查,帮助用户正确完成接口授权与访问验证。

40

2026.11.06

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
GDB Reference Card
GDB Reference Card

共0课时 | 0人学习

《Debugging with GDB》用户手册
《Debugging with GDB》用户手册

共0课时 | 0人学习

Valgrind FAQ
Valgrind FAQ

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn