c++ - 为什么 std::copy() 需要 std::back_inserter 插入到具有足够容量的向量中?
问题描述
参考代码:
#include <vector>
#include <algorithm>
#include <string>
#include <iostream>
void print(std::string label, std::vector<int> & arr) {
std::cout << label << ":" << " size: " << arr.size() << " cap: " << arr.capacity() << " [ ";
for (auto elem : arr) {
std::cout << elem << " ";
}
std::cout << " ] " << std::endl;
}
void reserve_dest_use_begin() {
std::vector<int> s_arr = {0, 1, 2, 3, 4, 5};
print("source", s_arr);
std::vector<int> d_arr;
d_arr.reserve(3);
print("dest", d_arr);
auto min_elems = std::min(s_arr.size(), d_arr.capacity());
std::cout << "COPYING FIRST" << min_elems << "3 FROM SOURCE TO DEST" << std::endl;
std::copy(s_arr.begin(), s_arr.begin() + min_elems, d_arr.begin());
print("source", s_arr);
print("dest", d_arr);
}
void reserve_dest_use_back_inserter() {
std::vector<int> s_arr = {0, 1, 2, 3, 4, 5};
print("source", s_arr);
std::vector<int> d_arr;
d_arr.reserve(3);
print("dest", d_arr);
auto min_elems = std::min(s_arr.size(), d_arr.capacity());
std::cout << "COPYING FIRST" << min_elems << " ELEMENTS FROM SOURCE TO DEST" << std::endl;
std::copy(s_arr.begin(), s_arr.begin() + min_elems, std::back_inserter(d_arr));
print("source", s_arr);
print("dest", d_arr);
}
int main() {
std::cout << "RESERVE DEST ARR. USE BEGIN() TO COPY" << std::endl;
reserve_dest_use_begin();
std::cout << "RESERVE DEST ARR. USE BACK_INSERTER() TO COPY" << std::endl;
reserve_dest_use_back_inserter();
输出:
RESERVE DEST ARR USE BEGIN() TO COPY
source: size: 6 cap: 6 [ 0 1 2 3 4 5 ]
dest: size: 0 cap: 3 [ ]
COPYING FIRST 3 ELEMENTS FROM SOURCE TO DEST
source: size: 6 cap: 6 [ 0 1 2 3 4 5 ]
dest: size: 0 cap: 3 [ ]
=============================================
RESERVE DEST ARR USE BACK_INSERTER() TO COPY
source: size: 6 cap: 6 [ 0 1 2 3 4 5 ]
dest: size: 0 cap: 3 [ ]
COPYING FIRST 3 ELEMENTS FROM SOURCE TO DEST
source: size: 6 cap: 6 [ 0 1 2 3 4 5 ]
dest: size: 3 cap: 3 [ 0 1 2 ]
在这两种情况下,目标阵列都有足够的容量。cppreference的文档表明:
Copies the elements in the range, defined by [first, last), to another range beginning at d_first.
1) Copies all elements in the range [first, last) starting from first and proceeding to last - 1. The behavior is undefined if d_first is within the range [first, last). In this case, std::copy_backward may be used instead.
指向的d_arr.begin()
源范围之外的范围,但在提供的示例中,尽管基础向量具有足够的容量[first, last)
,但我需要使用std::back_inserter()
复制而不是仅提供。d_arr.begin()
该std::back_inserter()
操作是优化为仅 memmove 内存块,还是推回每个元素?cppreference 的注释指出:
In practice, implementations of std::copy avoid multiple assignments and use bulk copy functions such as std::memmove if the value type is TriviallyCopyable and the iterator types satisfy LegacyContiguousIterator.
但是,std::back_inserter()
我怀疑它不会与memmove
.
总而言之,我有以下问题:
- 当底层向量有足够的容量时,为什么我不能
d_arr.begin()
用作OutputIt
in ?std::copy
- 使用是否
std::back_inserter()
针对批量复制范围进行了优化?
编辑:
我想我是从错误的角度提出这个问题的。评论中已经澄清了我想要做的操作是insert()
而不是copy()
. 我的具体用例是我反复clear()
将d_arr
一个子向量s_arr
从d_arr
. 我试图避免重新分配我的d_arr
. 然而,因为d_arr
被清除,虽然它确实有足够的容量,但它没有大小,这意味着没有要复制的元素。相反,我真正想做的是从s_arr
into插入一个子向量d_arr
。
d_arr.insert(d_arr.begin(), s_arr.begin(), s_arr.begin() + min_elems)
解决方案
当基础向量有足够的容量时,为什么我不能在 std::copy 中使用 d_arr.begin() 作为 OutputIt?
因为目标向量是空的,因此会std::copy
溢出向量(因为任何元素的赋值都超出了空向量的范围)。
std::back_inserter() 操作是否优化为仅 memmove
它可能是。它甚至可能被优化为更快的东西。
使用 std::back_inserter() 是否针对批量复制范围进行了优化?
给定足够聪明的优化器,是的。
使用适当的 vector 构造函数会比std::copy
. 既适用于代码阅读者,也适用于优化者。
推荐阅读
- r - modelvalid:用于 GmAMisc 中的二进制 Logistic 回归内部验证的 R 函数:“Gianmarco Alberti”
- javascript - 如何让 multerS3 将一组文件上传到我的存储桶?
- javascript - 我在这个 php 脚本中哪里出了问题来根据无线电输入操作字符串
- html - HTML - 我应该使用什么正确的标签?
- flutter - 颤振忽略按钮并执行功能
- reactjs - 尝试导入错误:“withLeaflet”未从“react-leaflet”导出
- typescript - 打字稿歧视联合类型安全不适用于子对象?
- sql-server - CREATE TABLE 中的 STATISTICS_INCREMENTAL
- java - 删除应用已配置的已保存网络
- r - 按组和时间“窗口”计算最大值