一、什么是浅拷贝?什么是深拷贝?
以下面这个函数为例,如图:
class Example {
public:
int* data;
int size;
// 普通构造函数:初始化数组数据
Example(int n) : size(n) {
data = new int[size];
// 给数组赋值:[0,1,2,3]
for (int i = 0; i < size; i++) {
data[i] = i;
}
}
// 拷贝构造函数
Example(const Example& other) : size(other.size) {
data = new int[size];
std::copy(other.data, other.data + size, data); //深拷贝
cout << "拷贝构造函数\n";
}
// 打印数组内容
void print() {
for (int i = 0; i < size; i++) {
cout << data[i] << " ";
}
cout << endl;
}
~Example() {
delete[] data;
}
};
这个函数实现的就是深拷贝,是需要我们手动去实现的。如果我们不去实现拷贝构造函数,编译器默认会生成浅拷贝的拷贝构造函数,类似如下代码,如图:
Example(const Example& other) : size(other.size) {
data = other.data;//浅拷贝
}
浅拷贝的缺点:
data = other.data只是让新对象的data指针指向other.data的内存地址,没有新分配内存;- 当原对象 / 新对象析构时,会重复释放同一块内存,导致程序崩溃;
- 而我们的写法是深拷贝:先分配新内存,再拷贝数据,两个对象的
data指向不同内存,互不影响。
二、深拷贝的写法
Example(const Example& other) : size(other.size) {
data = new int[size];
std::copy(other.data, other.data + size, data); //深拷贝
cout << "拷贝构造函数\n";
}
在这里我们将other的size给到新对象的size,通过std::copy将原对象other的数组内容完整复制到新分配的内存中。(深拷贝的核心)
std::copy的作用?
作用是把一段连续内存中的数据,按顺序拷贝到另一段连续内存中。
这行代码,本质是:把 other.data 指向的数组中,从起始位置到 size 个元素的所有数据,拷贝到 data 指向的内存地址开始的位置。
参数逻辑:遵循 “左闭右开” 原则,[起始地址, 结束地址),总共拷贝 结束地址 - 起始地址 个元素;
除了std::copy,还有什么方法实现深拷贝?
1、手写 for 循环
Example(const Example& other) : size(other.size) {
data = new int[size]; // 先分配内存
// 替代std::copy的for循环
for (int i = 0; i < size; i++) {
data[i] = other.data[i]; // 逐个拷贝元素
}
std::cout << "拷贝构造函数\n";
}
- 优点:新手易理解,无需依赖
<algorithm>头文件; - 缺点:代码行数多,对于复杂类型 / 大数组,效率不如
std::copy(std::copy是标准库优化过的);
2、C++11 及以上:std::uninitialized_copy
如果你的数组存储的是非基础类型(比如自定义类对象),std::uninitialized_copy 更合适 —— 它会在 “未初始化的内存” 上直接构造对象(而不是先默认构造再赋值),效率更高且更安全。
#include <memory> // 需包含这个头文件
Example(const Example& other) : size(other.size) {
data = new int[size];
// 替代std::copy,用法和std::copy几乎一致
std::uninitialized_copy(other.data, other.data + size, data);
std::cout << "拷贝构造函数\n";
}
- 优点:对自定义对象更高效、更安全(避免默认构造 + 赋值的额外开销);
- 缺点:需要依赖
<memory>头文件,对 int 等基础类型和std::copy效果无差异; - 适用场景:数组存储自定义类对象、追求极致内存效率时。
3、C 语言风格:memcpy(适合基础类型)
Example(const Example& other) : size(other.size) {
data = new int[size];
// 替代std::copy:按字节拷贝,sizeof(int)*size 是总字节数
memcpy(data, other.data, sizeof(int) * size);
std::cout << "拷贝构造函数\n";
}
- 优点:基础类型拷贝效率极高(直接操作内存),代码简洁;
- 缺点:
- 仅适用于 POD 类型(基础类型、简单结构体,无自定义构造 / 析构的类型);
- 用于自定义类对象时,会导致浅拷贝(比如对象里有
char*指针,只会拷贝指针地址,而非字符串内容);
- 适用场景:数组存储 int/char 等基础类型、追求极致性能时。
综上所述,std::copy是比较通用且适配所有类型的,同时标准库有一定优化,其他都是按需选择。
这里顺便说一下,std::copy和memcpy的区别
memcpy —— 本质是按 “字节” 无脑拷贝
解释:它只拷贝字节,对自定义对象中的指针,仅复制指针的地址值,不拷贝指针指向的内容,因此是浅拷贝;
std::copy —— 本质是按 “类型” 调用赋值逻辑
解释:它按元素类型调用赋值运算符,只要你为自定义类型实现了深拷贝的 operator=(或拷贝构造),就能实现真正的深拷贝;
977



被折叠的 条评论
为什么被折叠?



