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");

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

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

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

发生了什么?

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

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

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

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

深拷贝:独立账户

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

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

发生了什么?

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

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

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

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

最简记忆法:

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

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

相关推荐
2401_892070982 天前
【Linux C++ 日志系统实战】LogFile 日志文件管理核心:滚动策略、线程安全与方法全解析
linux·c++·日志系统·日志滚动
yuzhuanhei2 天前
Visual Studio 配置C++opencv
c++·学习·visual studio
Wenweno0o2 天前
0基础Go语言Eino框架智能体实战-chatModel
开发语言·后端·golang
chenjingming6662 天前
jmeter线程组设置以及串行和并行设置
java·开发语言·jmeter
cch89182 天前
Python主流框架全解析
开发语言·python
不爱吃炸鸡柳2 天前
C++ STL list 超详细解析:从接口使用到模拟实现
开发语言·c++·list
十五年专注C++开发2 天前
RTTR: 一款MIT 协议开源的 C++ 运行时反射库
开发语言·c++·反射
Momentary_SixthSense2 天前
设计模式之工厂模式
java·开发语言·设计模式
‎ദ്ദിᵔ.˛.ᵔ₎2 天前
STL 栈 队列
开发语言·c++
勿忘,瞬间2 天前
数据结构—顺序表
java·开发语言