std::copy不能直接复制c风格数组,必须传入同类型迭代器(如指针);正确写法为std::copy(src, src + n, dst),目标空间须预先分配且足够大,元素需支持拷贝赋值。

std::copy 不能直接复制 C 风格数组,必须传迭代器
很多人写 std::copy(arr1, arr2, 5) 或类似形式,编译直接报错——std::copy 第一、二个参数必须是同类型迭代器(或指针),第三个是目标起始位置,不是长度。C 风格数组名本身不是迭代器,但数组首地址可转为指针,而指针天然满足迭代器要求。
正确做法是用数组名(退化为指针)或 &arr[0] 表示起始,配合 &arr[n] 表示结束(注意:是“尾后”位置,非最后一个元素):
int src[3] = {1, 2, 3};
int dst[3];
std::copy(src, src + 3, dst); // ✅ 正确:src 是 int*,src + 3 是 int*
目标空间必须已分配且足够大,否则行为未定义
std::copy 不负责内存管理,只做逐元素赋值。如果目标数组没声明、长度不够,或指向野指针,运行时可能崩溃、静默越界或数据错乱,且编译器几乎不报错。
- 目标数组必须在调用前声明好,大小 ≥ 源范围长度
- 用
std::vector时需先调用resize()或确保容量足够;仅reserve()不够 - 复制到
std::back_inserter可自动扩展容器,但那是std::copy的变体用法,不是原地覆盖
复制对象时要注意拷贝构造和赋值是否可用
如果数组元素是自定义类,std::copy 内部调用的是 T 的拷贝赋值运算符(operator=),而非拷贝构造函数。这意味着:
- 目标位置必须已存在有效对象(例如
std::vector<t>(n)</t>构造出 n 个默认对象),否则对未初始化内存赋值会 UB - 类的
operator=必须是 public 且无异常(或至少不抛异常,否则可能破坏强异常安全) - 若想用移动语义,应改用
std::move_iterator包装源迭代器,再配合std::copy
替代方案:std::array 和 std::vector 更安全、更常用
纯 C 风格数组 + std::copy 容易因手算长度出错(比如写成 src + 4 而实际只有 3 个元素)。现代 C++ 中,优先考虑:
-
std::array<int> a = {1,2,3}, b;</int>→std::copy(a.begin(), a.end(), b.begin());(长度由类型携带,不会错) -
std::vector<int> v1 = {1,2,3}, v2;</int>→v2.resize(v1.size()); std::copy(v1.begin(), v1.end(), v2.begin()); - 或者一步到位:
v2.assign(v1.begin(), v1.end());(更简洁,且自动处理容量)
真正需要 std::copy 的典型场景,其实是跨容器/混合类型搬运,比如把 std::vector 复制进 C 数组作 C API 输入——这时才显出它“泛型搬运工”的价值,而不是用来替代 = 或 assign。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











