为何用std::copy复制std::array到std::vector时vec.begin()无效?
我尝试使用std::copy将std::array复制到std::vector中。根据cppReference,std::copy的原型为:
std::copy(InputIt first, InputIt last, OutputIt d_first)
其中OutputIt d_first代表目标范围的起始位置。
我据此编写了如下代码:
std::array<int, 10> arr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; std::vector<int> vec; std::copy(arr.begin(), arr.end(), vec.begin());
但代码未达到预期效果,无法将array复制到vector中。
经搜索得知正确代码应为:
std::array<int, 10> arr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; std::vector<int> vec; std::copy(arr.begin(), arr.end(), std::back_inserter(vec));
我的问题是:为何第一段代码无法生效?vec.begin()难道不属于代表目标起始位置的OutputIt d_first吗?
第一段代码失效的核心原因是:空vector的begin()指向的是无效的、不可写入的位置。
std::copy的工作逻辑是将源范围的元素逐个赋值到目标迭代器指向的位置,它不会自动为目标容器分配内存或扩展容器。这要求目标迭代器d_first指向的范围必须已经有足够的空间来容纳所有要复制的元素——简单说就是,目标容器的大小至少要等于源范围的元素数量。
当你创建空std::vector<int> vec;时,vec的大小为0,内部没有分配存储元素的内存。此时vec.begin()和vec.end()是相等的,指向的是容器末尾之后的“尾后迭代器”,往这个位置赋值属于未定义行为,可能导致程序崩溃、数据损坏,或者表面上没有任何效果。
而std::back_inserter(vec)返回的是一个插入迭代器(std::back_insert_iterator),它重载了赋值运算符:当std::copy尝试给这个迭代器赋值时,实际上会调用vec.push_back(),自动为vector分配内存(如果当前容量不足)并将元素添加到容器末尾,完美适配空vector的场景。
另外还有一种替代方案:提前给vector分配足够的空间,比如:
std::vector<int> vec(arr.size()); // 提前初始化vec的大小为10,分配对应内存 std::copy(arr.begin(), arr.end(), vec.begin());
此时vec.begin()指向的是有效的、可写入的内存位置,std::copy就能正常完成赋值操作。
内容的提问来源于stack exchange,提问作者user17849446

