如果我为矢量保留了一些空间,然后我用std::copy_n()
复制了一些值,我可以正确地复制和访问这些值,但矢量的大小仍为零。这是预期的行为吗?我应该调整向量的大小,即使它没有效率吗?
#include <algorithm>
#include <iostream>
#include <vector>
int main()
{
std::vector<double> src, dest;
for(double x = 0.0; x < 100.0; ++x)
src.push_back(x);
dest.reserve(src.size());
std::copy_n(src.cbegin(), src.size(), dest.begin());
std::cout << "src.size() = " << src.size() << std::endl;
std::cout << "dest.size() = " << dest.size() << std::endl;
for(size_t i = 0; i < src.size(); ++i)
std::cout << dest[i] << " ";
}
编译器测试:clang,gcc,Visual C ++
答案 0 :(得分:5)
但矢量的大小仍为零
std::copy_n
不会改变容器的大小,只需复制值并逐步执行迭代器;它甚至没有关于容器的任何信息。因此代码具有未定义的行为,即使它似乎工作正常。
我应该调整矢量大小,即使效率不高吗?
是的,您可以使用std::vector::resize
代替std::vector::reserve
来解决问题。您可能已经想到,这意味着所有元素将首先由resize
构建,然后由copy_n
分配。
您可以使用std::back_inserter,它将通过调用容器的push_back()
成员函数(即直接构造元素)将元素附加到容器的末尾,从而增加容器的大小。 e.g。
dest.reserve(src.size());
std::copy_n(src.cbegin(), src.size(), std::back_inserter(dest));
答案 1 :(得分:2)
关于标准库算法要记住的关键是它们在范围上运行,而不是在容器上运行。容器是您可以创建范围的方法之一,但它们不是唯一的方法。将结果写入范围的算法假定它们写入有效位置;他们没有,也不能,扩大他们写作的范围。
因此,当您致电std::copy_n
时,您必须提供足够大的范围来保存结果。这意味着使用dest.resize(src.size());
设置范围,而不仅仅使用dest.reserve(std.size());
分配内存。
或者,您可以通过使用std::back_inserter(dest)
而不是dest.begin()
调用算法来提供一个知道它附加到容器并需要调整大小的范围。
答案 2 :(得分:0)
std :: vector具有大小和容量。它保留了比插入更快更多所需的空间。 reserve 可让您指定该容量,而调整大小会更改矢量的实际大小。
答案 3 :(得分:0)
在调用dest
之后,您的reserve
已分配的内存用于存储元素,但它不调用构造函数并且实际上是空的,因此您的代码会导致UB。使用resize
来实际创建这些元素,然后就可以了。
dest.resize(src.size());
std::copy_n(src.cbegin(), src.size(), dest.begin());
std::cout << "src.size() = " << src.size() << std::endl;
std::cout << "dest.size() = " << dest.size() << std::endl;
for(size_t i = 0; i < src.size(); ++i)
std::cout << dest[i] << " ";