0

0

c++深拷贝与浅拷贝区别_c++拷贝构造函数详解

冰火之心

冰火之心

发布时间:2026-01-08 19:11:04

|

858人浏览过

|

来源于php中文网

原创

浅拷贝仅复制指针导致共享内存,深拷贝需手动分配并复制数据;拷贝构造函数在对象初始化、值传递参数、返回局部对象时调用;必须同时重载拷贝构造函数和operator=以避免行为不一致,并注意自赋值、异常安全及元信息同步。

c++深拷贝与浅拷贝区别_c++拷贝构造函数详解

浅拷贝只是复制指针,深拷贝才真正复制数据

默认的拷贝构造函数和赋值运算符执行的是浅拷贝——它把对象里的每个字节原样复制过去。如果类里有 char*int* 或其他裸指针成员,浅拷贝后两个对象会指向同一块堆内存。一旦其中一个析构时调用 delete,另一方再访问就是野指针;若两次析构,还会触发 double free 错误。

深拷贝必须在拷贝构造函数和 operator= 中手动分配新内存,并把原始数据逐字节或按逻辑复制过去。这是资源管理的基本守则,不写就会出问题。

拷贝构造函数什么时候被调用

它不是只在 A b = a; 这种写法里触发。以下场景都会调用:

  • 用一个已存在对象初始化新对象:A b(a);A b = a;
  • 函数传参时以值传递方式接收对象:void func(A x) { ... } 调用时 func(a)
  • 函数返回局部对象(且未被编译器优化掉):A create() { A x; return x; }

注意:现代编译器普遍启用 RVO/NRVO 优化,可能跳过拷贝构造。但逻辑上仍需正确实现,否则关掉优化或换编译器就崩。

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

必须同时重载拷贝构造函数和 operator=

只写拷贝构造函数而忽略赋值运算符,或反过来,会导致行为不一致。比如:

PodLM
PodLM

PodLM是一款强大的AI播客生成工具

下载
A a;
A b;
b = a; // 调用 operator=,若没重载,就是浅拷贝
A c = a; // 调用拷贝构造函数,若重载了,是深拷贝

这种不对称极易引发隐性 bug。标准做法是遵循“三法则”(C++11 后为“五法则”):只要写了析构函数、拷贝构造函数、拷贝赋值运算符中的任一个,另外几个通常也得自己写。

常见疏漏点:

  • operator= 忘记处理自赋值:a = a; 会导致先 delete 再访问已释放内存
  • 拷贝构造函数里调用 new 失败未检查,抛出异常后对象处于半构造状态
  • 没有把源对象的非指针成员(如 size_t len)一并复制,导致新对象元信息错乱

用 std::string 和 std::vector 可以绕过手写深拷贝

它们内部已经实现了正确的深拷贝语义。如果你的类里原来用 char* 存字符串,换成 std::string;用 int* + size_t 管理数组,换成 std::vector,那么默认生成的拷贝构造函数就能安全工作。

但这不等于可以忽视原理——当涉及文件句柄、socket、shared memory 等系统资源时,依然要手动管理。而且,有些老项目或嵌入式环境禁用 STL,这时深拷贝逻辑逃不掉。

真正容易被忽略的是:即使用了 std::vector,若类中还有裸指针成员(比如缓存用的 float* m_cache),那依然得自己写深拷贝。别以为加了 STL 就万事大吉。

相关专题

更多
string转int
string转int

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

315

2023.08.02

css中float用法
css中float用法

css中float属性允许元素脱离文档流并沿其父元素边缘排列,用于创建并排列、对齐文本图像、浮动菜单边栏和重叠元素。想了解更多float的相关内容,可以阅读本专题下面的文章。

556

2024.04.28

C++中int、float和double的区别
C++中int、float和double的区别

本专题整合了c++中int和double的区别,阅读专题下面的文章了解更多详细内容。

98

2025.10.23

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

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

1463

2023.10.24

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

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

227

2024.02.23

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

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

85

2025.10.17

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

253

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

206

2023.09.04

Golang 分布式缓存与高可用架构
Golang 分布式缓存与高可用架构

本专题系统讲解 Golang 在分布式缓存与高可用系统中的应用,涵盖缓存设计原理、Redis/Etcd集成、数据一致性与过期策略、分布式锁、缓存穿透/雪崩/击穿解决方案,以及高可用架构设计。通过实战案例,帮助开发者掌握 如何使用 Go 构建稳定、高性能的分布式缓存系统,提升大型系统的响应速度与可靠性。

59

2026.01.09

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
CSS3 教程
CSS3 教程

共18课时 | 4.4万人学习

Sass 教程
Sass 教程

共14课时 | 0.7万人学习

Pandas 教程
Pandas 教程

共15课时 | 0.9万人学习

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

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号