std :: copy_n不会更改目标向量大小

时间:2017-02-04 16:12:03

标签: c++ c++11 copy stdvector stl-algorithm

如果我为矢量保留了一些空间,然后我用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 ++

4 个答案:

答案 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] << "  ";