深拷贝数组必须手动分配新内存并逐元素复制;原生数组不支持深拷贝语义,直接赋值会编译错误;new+循环赋值安全通用,malloc+memcpy仅适用于POD类型;memcpy不调用构造/析构函数,误用于非POD类型(如std::string)将导致悬空指针。

深拷贝数组必须自己分配新内存
在 C++ 中,原生数组(如 int arr[10])本身不支持“深拷贝”语义——它没有拷贝构造函数或赋值运算符。所谓“深拷贝数组”,本质是:申请一块**独立的新内存**,再把原数组内容逐字节或逐元素复制过去。如果你直接写 arr2 = arr1(对原生数组),编译器会报错;如果用指针或动态数组,不手动 new + copy,就只是浅拷贝(两个指针指向同一块内存)。
常见错误现象:delete[] ptr1 后再访问 ptr2,触发野指针崩溃;或修改 ptr2[i] 却意外改了 ptr1[i]。
- 使用
new+ 循环赋值:安全、可读、支持类类型(调用构造/析构) - 使用
malloc+memcpy:仅适用于 POD 类型(如int、double、纯 C 结构体),不调用构造/析构函数 - 避免
std::array或std::vector时还手写拷贝——它们默认就是深拷贝
memcpy 只适合 POD 类型的按字节拷贝
memcpy 是 C 标准库函数,行为是“从 src 地址开始,连续复制 n 字节到 dst”。它不管数据类型,也不调用任何构造函数或析构函数。这意味着:只要源和目标内存布局一致、且对象不含指针/虚表/非平凡成员,memcpy 才等价于深拷贝。
典型误用:memcpy(dst, src, sizeof(std::string)) —— std::string 内部有指针,memcpy 只复制了指针值,造成双重释放或悬空引用。
立即学习“C++免费学习笔记(深入)”;
- ✅ 安全:复制
int*、double[100]、struct { int x; float y; }* - ❌ 危险:复制含
std::string、std::vector、虚函数、自定义构造函数的类对象 - 参数顺序固定:
memcpy(dst, src, n),别把 src 和 dst 写反,也别忽略n是字节数(不是元素个数)
循环赋值更通用,但要注意构造语义
对动态分配的数组(如 T* src = new T[n]),用循环做深拷贝是最直观的方式:
for (int i = 0; i < n; ++i) {
dst[i] = src[i]; // 调用 T 的拷贝赋值运算符
}这行代码是否真正完成深拷贝,取决于 T 自身的实现。例如:
-
T = int:简单赋值,效果同memcpy -
T = std::string:调用std::string::operator=,内部会重新分配内存,真正深拷贝字符串内容 -
T是自定义类:需确保已正确定义拷贝赋值运算符(或依赖编译器生成的,默认行为对含指针成员仍是浅拷贝)
性能上,循环比 memcpy 稍慢(函数调用开销、可能的分支),但语义明确、类型安全、可调试。
最容易被忽略的点:析构与所有权归属
无论用 memcpy 还是循环,你手动分配了内存(new T[n]),就必须手动释放(delete[] ptr)。C++ 不会自动追踪谁拥有这块内存。
更隐蔽的问题是:如果原数组里存的是指针(如 MyClass** arr),那“深拷贝数组”到底要不要也深拷贝每个 MyClass* 指向的对象?这完全由业务逻辑决定,memcpy 和循环都只处理第一层——它们复制的是指针值,不是指针所指内容。
建议:除非有极致性能要求且确认是 POD,否则优先用 std::vector。它的拷贝构造自动完成深拷贝,内存管理零出错风险。











