std::array、std::vector 和 std::copy 之间的交互

0 c++ arrays containers vector

我正在尝试将 a 复制到usingstd::array中。std::vectorstd::copy

根据cppReference,其原型std::copy为:

std::copy(InputIt first, InputIt last, OutputIt d_first)
Run Code Online (Sandbox Code Playgroud)

,其中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());
Run Code Online (Sandbox Code Playgroud)

然而,代码并没有像我预期的那样工作,它只是没有将 复制arrayvector.

根据快速谷歌搜索,代码应该是:

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));
Run Code Online (Sandbox Code Playgroud)

我的问题是,为什么第一个代码不起作用?

vec.begin()被视为OutputIt d_first,其中我的理解是“代表目的地第一个位置的迭代器”?

use*_*522 5

vec.begin() 一个输出迭代器,原则上按照您尝试的方式使用它没有问题。然而,vec.begin()它是指向向量当前保存的范围开头的迭代器。它不是附加到向量的迭代器。

由于您的向量最初是空的,因此引用的有效范围vec.begin()也是空的,但是您随后尝试通过调用将多个元素分配到该范围中std::copy,从而导致未定义的行为。

另一方面,std::back_inserter(vec)它不是向量当前保存的范围上的迭代器,而是一个纯输出迭代器,每次分配新元素时都会将新元素附加到容器中。

vec.begin()如果您在使用之前调整了向量的大小std::copy也很好,因为引用的范围vec.begin()将足够大以容纳您从中复制的数组中的所有元素:

std::vector<int> vec(arr.size());
std::copy(arr.begin(), arr.end(), vec.begin());
Run Code Online (Sandbox Code Playgroud)

你也可以只写

std::vector<int> vec(arr.begin(), arr.end());
Run Code Online (Sandbox Code Playgroud)

这将直接确定为向量的存储分配的正确大小并将数组的元素复制到其中。这比其他两种选择更有效。


从 C++17 开始,如果您希望值类型等于数组的类型,也可以删除值类型。通过 CTAD 可以推导出:

std::vector vec(arr.begin(), arr.end());
Run Code Online (Sandbox Code Playgroud)

从 C++23 开始,您还可以编写

std::vector vec(arr);
Run Code Online (Sandbox Code Playgroud)

达到同样的效果。