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");
我的账号.添加歌单("我最爱的歌");
// 浅拷贝:把你的账号信息告诉朋友
网易云账号 朋友的账号 = 我的账号; // 浅拷贝
发生了什么?
-
朋友没有自己的账号,只是知道了你的账号密码
-
你们登录的是同一个账号
-
如果朋友删除了一首歌 → 你的歌单也没了!
-
如果朋友改了密码 → 你也登录不了了!
深拷贝:独立账户
// 深拷贝:给朋友创建全新账号
网易云账号 朋友的账号 = 我的账号.深拷贝();
发生了什么?
-
网易云为朋友新建了一个完全独立的账号
-
把你所有的歌单、收藏复制一份到新账号
-
朋友删歌 → 你的歌单不受影响
-
朋友改密码 → 你的密码不变
最简记忆法:
-
浅 = 浅尝辄止,只复制表面(指针)
-
深 = 深入到底,复制全部内容