0

0

C++中的浅拷贝和深拷贝有什么区别?(指针地址复制与堆内存独立申请)

裘德小鎮的故事

裘德小鎮的故事

发布时间:2026-01-12 10:09:32

|

335人浏览过

|

来源于php中文网

原创

浅拷贝仅复制指针值,导致多对象共享同一内存,引发use-after-free或double free;深拷贝需重载拷贝构造、赋值运算符和析构函数,手动分配并复制内存;现代C++推荐用vector、string或unique_ptr替代裸指针。

c++中的浅拷贝和深拷贝有什么区别?(指针地址复制与堆内存独立申请)

浅拷贝只是复制指针值,不是复制它指向的内容

当你用默认拷贝构造函数或赋值运算符处理含 int* 这类裸指针的类时,编译器只做位拷贝:把原对象里指针变量的值(即内存地址)直接复制过去。两个对象的指针成员指向同一块堆内存。

这会导致后续操作出问题,比如其中一个对象析构时调用 delete,另一对象再访问该指针就会触发 use-after-free;或者两个对象都尝试 delete 同一块内存,引发 double free 错误。

常见错误现象:

  • 程序在第二次 delete 时崩溃(glibc 报 double free or corruption
  • 修改一个对象的数据,另一个对象的对应字段也跟着变
  • Valgrind 报告 Invalid read/writeUse of uninitialised value

深拷贝需要手动申请新堆内存并逐字节复制内容

实现深拷贝的关键是:在拷贝构造函数和 operator= 中,不复用原指针,而是用 new 分配一块大小相同的新内存,再用 memcpy 或循环把原数据拷过去。

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

必须同时满足三个条件,才算完整实现深拷贝:

  • 重载拷贝构造函数,内部用 new 分配内存 + std::copy 或循环复制数据
  • 重载赋值运算符,先检查自赋值(if (this == &other)),再释放当前内存,再分配+复制
  • 重载析构函数,确保用 delete[](对数组)或 delete(对单个对象)释放自己申请的内存

漏掉任意一项,都可能造成内存泄漏、重复释放或悬空指针。

CG Faces
CG Faces

免费的 AI 人物图像素材网站

下载

现代 C++ 更推荐用智能指针或容器替代裸指针

手写深拷贝容易出错,且难以兼顾异常安全。C++11 起,应优先用 std::vectorstd::stringstd::unique_ptr 替代裸指针管理堆内存。

例如:

class Data {
private:
    std::vector data_; // 自动深拷贝,无需手写拷贝函数
public:
    Data(const std::vector& d) : data_(d) {}
    // 编译器生成的拷贝构造函数已正确处理深拷贝
};

若必须用裸指针,至少用 std::unique_ptr,它的拷贝被禁用,移动时自动转移所有权,从根本上避免浅拷贝误用。

调试时怎么快速判断是不是浅拷贝导致的问题

观察两个对象中指针成员的地址值是否一致:

Data a({1,2,3});
Data b = a; // 假设未定义拷贝构造函数
std::cout << "a.ptr: " << (void*)a.ptr_ << "\n";
std::cout << "b.ptr: " << (void*)b.ptr_ << "\n"; // 若输出相同地址,就是浅拷贝

更可靠的方式是用 AddressSanitizer 编译运行:g++ -fsanitize=address -g,它会在发生 use-after-freedouble-free 时直接打印栈回溯。

真正麻烦的不是写深拷贝,而是忘记写——只要类里有裸指针或 FILE* 等资源句柄,就必须显式定义三法则(拷贝构造、赋值、析构),否则默认行为几乎总是错的。

相关专题

更多
string转int
string转int

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

315

2023.08.02

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、按位异或运算符等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

228

2024.02.23

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

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

85

2025.10.17

if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

731

2023.08.22

string转int
string转int

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

315

2023.08.02

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

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

534

2024.08.29

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

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

51

2025.08.29

c++主流开发框架汇总
c++主流开发框架汇总

本专题整合了c++开发框架推荐,阅读专题下面的文章了解更多详细内容。

97

2026.01.09

热门下载

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

精品课程

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

共18课时 | 4.4万人学习

Sass 教程
Sass 教程

共14课时 | 0.8万人学习

Pandas 教程
Pandas 教程

共15课时 | 0.9万人学习

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

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