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

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

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

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

发生了什么?

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

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

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

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

深拷贝:独立账户

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

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

发生了什么?

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

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

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

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

最简记忆法:

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

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

相关推荐
R&ain17 小时前
C++的内联函数
c++·算法
羑悻的小杀马特17 小时前
gflags+spdlog实战:C++命令行参数与高性能日志的极致搭配行动指南
c++·spdlog·gflags
智航GIS17 小时前
10.2 Requests库入门
开发语言·python
fpcc19 小时前
跟我学C++中级篇——Linux中文件和链接及重定向
linux·c++
Fcy64819 小时前
C++ set&&map的模拟实现
开发语言·c++·stl
你怎么知道我是队长1 天前
C语言---枚举变量
c语言·开发语言
李慕婉学姐1 天前
【开题答辩过程】以《基于JAVA的校园即时配送系统的设计与实现》为例,不知道这个选题怎么做的,不知道这个选题怎么开题答辩的可以进来看看
java·开发语言·数据库
吃茄子的猫1 天前
quecpython中&的具体含义和使用场景
开发语言·python
云栖梦泽1 天前
易语言中小微企业Windows桌面端IoT监控与控制
开发语言