1. 从拷贝构造函数说起
第一次在项目中遇到深浅拷贝问题是在三年前的一个多线程日志系统里。当时为了封装日志缓冲区的操作,我写了这样一个类:
cpp复制class LogBuffer {
public:
char* data;
size_t size;
LogBuffer(const char* str) {
size = strlen(str) + 1;
data = new char[size];
memcpy(data, str, size);
}
~LogBuffer() {
delete[] data;
}
};
看起来没什么问题对吧?直到我在另一个地方这样使用它:
cpp复制void processLog(LogBuffer buf) {
// 处理日志内容
}
int main() {
LogBuffer original("Hello World");
processLog(original); // 这里调用了默认的拷贝构造函数
// original.data 现在指向已释放的内存!
}
这就是典型的浅拷贝陷阱——默认的拷贝构造函数只是简单复制了指针值,导致两个对象指向同一块内存。当其中一个对象析构时,另一个对象的指针就变成了悬垂指针。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 深拷贝的实现方式
2.1 传统深拷贝方案
正确的做法是实现拷贝构造函数和拷贝赋值运算符:
cpp复制class LogBuffer {
public:
// ... 其他成员同上
LogBuffer(const LogBuffer& other) {
size = other.size;
data = new char[size];
memcpy(data, other.data, size);
}
LogBuffer& operator=(const LogBuffer& other) {
if (this != &other) {
delete[] data;
size = other.size;
data = new char[size];
memcpy(data, other.data, size);
}
return *this;
}
};
关键点:在拷贝赋值运算符中,一定要先检查自赋值情况(this == &other),否则在自赋值时会先删除自己的数据,导致后续拷贝出错。
2.2 深拷贝的性能代价
假设我们要拷贝一个包含百万条记录的容器:
code复制
