c++中如何实现深度拷贝数组_c++ std::copy与memcpy用法区别【详解】

std::copy适合对象数组的深度拷贝,memcpy仅适用于POD类型;前者调用拷贝构造或赋值运算符,后者为字节级复制,对非POD类型行为未定义。

std::copy 适合对象数组的深度拷贝,memcpy 只能用于 POD 类

直接结论:std::copy 会调用元素的拷贝构造函数或赋值运算符,能正确处理含指针、string、vector 等成员的对象;memcpy 是字节级内存复制,对非 POD(Plain Old Data)类型行为未定义——比如复制一个含 std::string 成员的 struct,memcpy 会导致两个对象共享同一块堆内存,析构时 double-free。

什么时候必须用 std::copy 而不能用 memcpy

以下情况 memcpy 会出错,必须用 std::copy

  • 数组元素是类类型且定义了非平凡拷贝构造函数(例如含 std::stringstd::vector、自定义析构逻辑)
  • 目标数组和源数组类型不同但可隐式转换(std::copy 支持类型转换,memcpy 不支持)
  • 使用自定义分配器或需要触发迭代器相关语义(如 std::copy 可配合 std::back_inserter
struct Person {
    std::string name;
    int age;
};
Person src[2] = {{"Alice", 30}, {"Bob", 25}};
Person dst[2];
// ✅ 正确:调用 string 的拷贝构造
std::copy(src, src + 2, dst);
// ❌ 危险:name 内部指针被位移复制,析构时崩溃
memcpy(dst, src, sizeof(Person) * 2);

memcpy 在什么场景下比 std::copy 更快且安全

memcpy 仅在满足所有下列条件时可安全替代 std::copy,且通常有性能优势(编译器可能内联为 SIMD 指令):

  • 元素类型是 POD:无用户定义构造/析构/赋值函数,无虚函数,无非静态引用成员
  • 源与目标内存不重叠(否则应改用 memmove
  • 你知道确切字节数,且地址对齐(现代编译器通常自动优化对齐访问)
// ✅ 安全且高效:int 是 POD,连续内存
int src[] = {1, 2, 3, 4};
int dst[4];
memcpy(dst, src, sizeof(int) * 4); // 比 std::copy 略快,尤其大数据量

std::copy 的常见误用与陷阱

即使类型安全,std::copy 也容易因迭代器错误导致越界或静默失败:

  • 目标空间不足:不会检查目标容量,写越界是未定义行为
  • 反向复制误用正向迭代器:std::copy 不自动适配 std::reverse_iterator,需显式用 std::copy_backward
  • 传入空指针或非法迭代器(如 end() 作为起始)不报错,但行为未定义
  • std::vector 使用原生指针时,若 vector realloc 导致迭代器失效,后续 copy 可能崩溃

建议始终搭配 std::vector::data() 或范围检查:

std::vector src = {1, 2, 3};
std::vector dst(src.size());
std::copy(src.begin(), src.end(), dst.begin()); // 安全:size 匹配

真正麻烦的不是选哪个函数,而是没想清楚「这个类型到底算不算 POD」——C++20 起可以用 std::is_trivially_copyable_v 编译期断言,但很多老项目连 都没引入。