C++中的深浅拷贝

1、浅拷贝

浅拷贝只复制对象的成员变量值,包括指针的值(地址),不复制指针指向的内容

#include <iostream>

#include <cstring>

class ShallowString {

private:

char* data;

public:

// 构造函数

ShallowString(const char* str = "") {

data = new char[strlen(str) + 1];

strcpy(data, str);

std::cout << "Constructor called for: " << data << std::endl;

}

// 析构函数

~ShallowString() {

std::cout << "Destructor called for: " << data << std::endl;

delete[] data;

}

// 默认拷贝构造函数(浅拷贝)

// 编译器自动生成:ShallowString(const ShallowString& other) : data(other.data) {}

void print() const {

std::cout << "Data: " << data << " (" << (void*)data << ")" << std::endl;

}

void modify(const char* newStr) {

strcpy(data, newStr);

}

};

void demonstrateShallowCopyProblem() {

std::cout << "=== 浅拷贝问题演示 ===" << std::endl;

ShallowString str1("Hello");

ShallowString str2 = str1; // 浅拷贝!

std::cout << "\n原始状态:" << std::endl;

str1.print();

str2.print();

std::cout << "\n修改str2:" << std::endl;

str2.modify("World");

std::cout << "\n修改后:" << std::endl;

str1.print(); // 也被修改了!

str2.print();

std::cout << "\n问题:两个对象共享同一块内存!" << std::endl;

std::cout << "更严重的问题:双重释放!" << std::endl;

}

/*

输出示例:

=== 浅拷贝问题演示 ===

Constructor called for: Hello

原始状态:

Data: Hello (0x...)

Data: Hello (0x...) // 相同地址!

修改str2:

修改后:

Data: World (0x...) // 两个都变了!

Data: World (0x...)

问题:两个对象共享同一块内存!

更严重的问题:双重释放!

Destructor called for: World

Destructor called for: World // 第二次释放同一内存 -> 程序崩溃!

*/

2、深拷贝

深拷贝会复制指针指向的实际内容,创建一个全新的内存区域。

#include <iostream>

#include <cstring>

class DeepString {

private:

char* data;

public:

// 构造函数

DeepString(const char* str = "") {

data = new char[strlen(str) + 1];

strcpy(data, str);

std::cout << "Constructor called for: " << data << " at " << (void*)data << std::endl;

}

// 深拷贝构造函数

DeepString(const DeepString& other) {

data = new char[strlen(other.data) + 1];

strcpy(data, other.data);

std::cout << "Deep copy constructor called" << std::endl;

std::cout << " From: " << other.data << " at " << (void*)other.data << std::endl;

std::cout << " To: " << data << " at " << (void*)data << std::endl;

}

// 深拷贝赋值运算符

DeepString& operator=(const DeepString& other) {

if (this != &other) { // 自赋值检查

delete[] data; // 释放原有内存

data = new char[strlen(other.data) + 1];

strcpy(data, other.data);

std::cout << "Deep copy assignment called" << std::endl;

}

return *this;

}

// 析构函数

~DeepString() {

std::cout << "Destructor called for: " << data << " at " << (void*)data << std::endl;

delete[] data;

}

void print() const {

std::cout << "Data: " << data << " (" << (void*)data << ")" << std::endl;

}

void modify(const char* newStr) {

strcpy(data, newStr);

}

};

void demonstrateDeepCopy() {

std::cout << "=== 深拷贝演示 ===" << std::endl;

DeepString str1("Hello");

DeepString str2 = str1; // 深拷贝

std::cout << "\n原始状态:" << std::endl;

str1.print();

str2.print();

std::cout << "\n修改str2:" << std::endl;

str2.modify("World");

std::cout << "\n修改后:" << std::endl;

str1.print(); // 保持不变

str2.print(); // 已修改

std::cout << "\n赋值操作:" << std::endl;

DeepString str3("Test");

str3 = str1; // 深拷贝赋值

str3.print();

}

/*

输出示例:

=== 深拷贝演示 ===

Constructor called for: Hello at 0x...

Deep copy constructor called

From: Hello at 0x...

To: Hello at 0x... // 不同地址!

原始状态:

Data: Hello (0x...)

Data: Hello (0x...) // 不同地址

修改str2:

修改后:

Data: Hello (0x...) // 保持不变

Data: World (0x...) // 已修改

赋值操作:

Constructor called for: Test at 0x...

Deep copy assignment called

Data: Hello (0x...)

Destructor called for: Hello at 0x...

Destructor called for: World at 0x...

Destructor called for: Hello at 0x...

*/

3、用通俗易懂的语言来说

浅拷贝:共享账号

想象你有一个网易云音乐账号(里面有你的歌单、收藏):

// 这是你的原始账号

网易云账号 我的账号("小明", "密码123");

我的账号.添加歌单("我最爱的歌");

// 浅拷贝:把你的账号信息告诉朋友

网易云账号 朋友的账号 = 我的账号; // 浅拷贝

发生了什么?

  • 朋友没有自己的账号,只是知道了你的账号密码

  • 你们登录的是同一个账号

  • 如果朋友删除了一首歌 → 你的歌单也没了!

  • 如果朋友改了密码 → 你也登录不了了!

深拷贝:独立账户

// 深拷贝:给朋友创建全新账号

网易云账号 朋友的账号 = 我的账号.深拷贝();

发生了什么?

  • 网易云为朋友新建了一个完全独立的账号

  • 把你所有的歌单、收藏复制一份到新账号

  • 朋友删歌 → 你的歌单不受影响

  • 朋友改密码 → 你的密码不变

最简记忆法:

  • = 浅尝辄止,只复制表面(指针)

  • = 深入到底,复制全部内容

相关推荐
还是阿落呀几秒前
基本控制结构2
c++
啧不应该啊2 分钟前
Day1 Python 与 C 的类型区别
c语言·开发语言
多思考少编码22 分钟前
PAT甲级真题1001 - 1005题详细题解(C++)(个人题解)
c++·python·最短路·pat·算法竞赛
cen__y26 分钟前
Linux07(信号01)
linux·运维·服务器·c语言·开发语言
xingpanvip1 小时前
星盘接口开发文档:星相日历接口指南
android·开发语言·前端·css·php·lua
guygg881 小时前
基于遗传算法的双层规划模型求解MATLAB实现
开发语言·matlab
凯瑟琳.奥古斯特1 小时前
SQLAlchemy核心功能解析
开发语言·python·flask
卷Java1 小时前
GPTQ vs AWQ vs GGUF:模型量化工具横向测评
开发语言·windows·python
极客智造2 小时前
C++ 标准 IO 流全详解:cin /cout/get /getline 原理、用法、区别与避坑
c++·io
charlie1145141912 小时前
嵌入式C++工程实践第20篇:GPIO 输入模式内部电路 —— 芯片是如何“听“到外部信号的
开发语言·c++·stm32·单片机