std::copy不能自动扩容,目标容器必须预先分配足够空间或使用back_inserter等适配器;直接向空vector的begin()拷贝会导致未定义行为。

std::copy 不能直接拷贝到空容器的末尾
很多人以为 std::copy 能像 push_back 那样自动扩容,结果程序崩溃或写入越界。它只是按给定目标迭代器“逐个赋值”,不检查容量、不调用 insert 或 push_back。目标容器必须已有足够空间,或你得提供能自动增长的迭代器。
常见错误现象:std::vector 目标为空时传入 v.begin(),导致未定义行为;或者目标大小不足,只覆盖前 N 个元素,后面数据残留。
- 正确做法:提前
resize目标容器(适合已知长度) - 或使用
std::back_inserter(适合未知长度,自动调用push_back) - 或用
std::inserter(适用于set/map等关联容器)
用 std::back_inserter 配合 std::copy 向 vector 尾部追加
这是最常用也最安全的“复制并增长”方式。它把目标容器包装成一个输出迭代器,每次赋值都等价于调用 push_back。
std::vector<int> src = {1, 2, 3};
std::vector<int> dst;
std::copy(src.begin(), src.end(), std::back_inserter(dst));
// dst 现在是 {1, 2, 3}
</int></int>
注意:std::back_inserter 只对支持 push_back 的容器有效(vector、deque、list),对 array 或原生数组无效。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 性能影响:每次插入都可能触发内存重分配(尤其
vector),若可预估大小,先reserve更高效 - 不能用于 const 容器或只读视图
- 返回的迭代器类型是
std::back_insert_iterator,不是普通指针,不能取地址或随机访问
复制到固定大小目标时,必须确保空间足够
如果目标容器已分配好空间(比如用 resize 或构造时指定大小),就可以直接用 begin() 作为目标迭代器 —— 这时 std::copy 是纯内存拷贝语义,效率最高。
std::vector<int> src = {10, 20, 30};
std::vector<int> dst(3); // 明确分配 3 个元素
std::copy(src.begin(), src.end(), dst.begin());
</int></int>
容易踩的坑:
- 误用
dst.data()替代dst.begin():虽然对vector等连续容器等价,但语义不同;data()是裸指针,丢失类型信息,且不适用于非连续容器 - 源范围长度超过目标空间:不会报错,但会越界写入,引发未定义行为
- 目标是
std::array:必须用arr.begin(),不能用&arr[0](后者类型为int*,和std::copy模板推导可能不匹配)
跨容器类型拷贝要注意元素兼容性
std::copy 不做类型转换,只调用目标位置的赋值运算符。源和目标元素类型不必完全相同,但必须满足:源类型能隐式转换为目标类型,或目标类型有接受源类型的赋值重载。
例如从 std::vector<double></double> 拷到 std::vector<int></int> 是合法的(double → int 截断转换),但反过来不行(int → double 可以,但若目标是 const int& 就不行)。
- 若涉及自定义类,确保有可用的拷贝赋值操作符(
operator=) - 移动语义不被
std::copy自动启用;如需移动,改用std::move_iterator包装源迭代器 - 对
std::string等含内部资源的类型,拷贝仍是深拷贝,不用担心浅拷贝问题
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










