std::copy要求源目标迭代器支持自增和解引用,目标空间须预先分配,否则导致未定义行为;可用back_inserter实现自动扩容,但性能略低;类型不匹配可能引发截断或编译失败;copy_n不检查源长度,防越界需手动校验。

std::copy 要求迭代器必须支持自增和解引用
直接用 std::copy 复制容器元素,前提是源和目标都提供合格的迭代器。比如 std::vector、std::list、std::array 都可以,但原生数组需手动传指针,std::forward_list 的 begin() 可用,但注意它不支持随机访问。
常见错误是把空容器的目标 end() 当作插入位置——std::copy 不会自动扩容,目标空间必须预先分配好:
std::vectorsrc = {1, 2, 3}; std::vector dst(3); // 必须提前分配至少 3 个元素 std::copy(src.begin(), src.end(), dst.begin()); // ✅
如果写成 std::vector 再调用 std::copy,就会写入未分配内存,触发未定义行为。
复制到 back_inserter 才能自动追加元素
想让目标容器动态增长,不能直接传 dst.begin(),得用 std::back_inserter 包装:
立即学习“C++免费学习笔记(深入)”;
std::vectorsrc = {1, 2, 3}; std::vector dst; std::copy(src.begin(), src.end(), std::back_inserter(dst)); // ✅ dst 自动 push_back
-
std::back_inserter返回的是一个输出迭代器,内部调用push_back - 仅适用于支持
push_back的容器(vector、deque、list),对std::array或只读容器无效 - 性能上比预分配略低(每次插入都要检查容量),但代码更安全、直观
复制时类型不匹配会编译失败或静默截断
std::copy 是按位复制,不做运行时类型检查。源和目标元素类型最好一致;若不同,依赖隐式转换是否合法:
- 从
long long复制到int:编译通过,但可能溢出(无警告) - 从
std::string复制到std::vector:编译失败,无隐式转换 - 自定义类之间复制:要求目标类型有匹配的构造函数或赋值操作符
更安全的替代是 std::transform 加显式转换逻辑,或者用容器自身的构造/赋值(如 dst.assign(src.begin(), src.end()))。
用 copy_n 替代 copy 可避免越界风险
当只知道要复制前 N 个元素,但不确定源容器大小时,std::copy 容易因迭代器超限崩溃。此时该用 std::copy_n:
std::vectorsrc = {10, 20}; std::vector dst(5); std::copy_n(src.begin(), 5, dst.begin()); // ❌ 运行时越界(src 只有 2 个)
不对——std::copy_n 第二个参数是数量,它自己会检查是否超出源范围吗?不会。它只保证最多取 N 个,但若源迭代器走不到第 N 个,行为仍是未定义。真正靠谱的做法是先比较大小,或改用 std::copy 配合 std::min:
auto n = std::min(src.size(), dst.size()); std::copy(src.begin(), src.begin() + n, dst.begin());
所以别迷信 copy_n 能防错,它只是接口更紧凑,责任仍在使用者手上。
最容易被忽略的一点:std::copy 不是“复制容器”,它只复制元素;容器本身的属性(如 capacity、分配器、节点结构)完全无关。拿 list 复制进 vector,得到的是连续内存里的副本,和原 list 再无关系。










