【问题标题】:STL vector reserve() and copy()STL 向量 reserve() 和 copy()
【发布时间】:2009-07-14 22:56:47
【问题描述】:

您好,

我正在尝试使用以下 2 行缩写的代码(完整的测试应用程序如下)从一个向量 (vec1) 复制到另一个向量 (vec2):

vec2.reserve( vec1.size() );
copy(vec1.begin(), vec1.end(), vec2.begin());

虽然对 vec2 的调用设置了向量 vec2 的容量,但将数据复制到 vec2 似乎并未填充从 vec1 到 vec2 的值。

用 push_back() 调用替换 copy() 函数可以正常工作。

我在这里错过了什么?

感谢您的帮助。 vectest.cpp 测试程序,然后是结果输出。

编译器:cygwin 上的 gcc 3.4.4。

自然

/**
 * vectest.cpp
 */

#include <iostream>
#include <vector>

using namespace std;

int main()
{
    vector<int> vec1;
    vector<int> vec2;

    vec1.push_back(1);
    vec1.push_back(2);
    vec1.push_back(3);
    vec1.push_back(4);
    vec1.push_back(5);
    vec1.push_back(6);
    vec1.push_back(7);

    vec2.reserve( vec1.size() );
    copy(vec1.begin(), vec1.end(), vec2.begin());

    cout << "vec1.size()     = " << vec1.size() << endl;
    cout << "vec1.capacity() = " << vec1.capacity() << endl;

    cout << "vec1: ";
    for( vector<int>::const_iterator iter = vec1.begin(); iter < vec1.end(); ++iter ) {
        cout << *iter << " ";
    }
    cout << endl;

    cout << "vec2.size()     = " << vec2.size() << endl;
    cout << "vec2.capacity() = " << vec2.capacity() << endl;
    cout << "vec2: ";
    for( vector<int>::const_iterator iter = vec2.begin(); iter < vec2.end(); ++iter ) {
        cout << *iter << endl;
    }

    cout << endl;
}

输出:

vec1.size()     = 7
vec1.capacity() = 8
vec1: 1 2 3 4 5 6 7 
vec2.size()     = 0
vec2.capacity() = 7
vec2: 

【问题讨论】:

    标签: c++ stl vector stl-algorithm


    【解决方案1】:

    如果向量属于同一类型,则使用复制构造或复制赋值:

    vec2(vec1);
    vec2 = vec1;
    

    如果向量不完全相同(可能是不同的分配器或其他东西,或者 vec1 是双端队列),您真正想要的是基于范围的构造函数或基于范围的分配:

    vec2(vec1.begin(), vec1.end()); // range-based constructor
    
    vec2.assign(vec1.begin(), vec1.end()); // range-based assignment
    

    如果你坚持使用std::copy,正确的方法是:

    copy(vec1.begin(), vec1.end(), back_inserter(vec2));
    

    由于保留空间不会使其可分配。 copy 通过将每个元素分配给它的新值来工作。所以 vec2.size() 在你的情况下至少需要和 vec1.size() 一样大。调用 reserve 实际上并不会改变向量的大小,只会改变它的容量。

    Effective STL 一书中,Scott Meyers 认为几乎所有用于插入的 std::copy 都应替换为基于范围的成员函数。建议你去拿一份,很好的参考!

    【讨论】:

    • 我认为您应该在最后一段中强调“成员函数”,我首先错过了它并想“什么?复制基于范围的!”这是一个很棒的建议,所以我们不希望人们错过它:)
    【解决方案2】:

    正如其他答案和 cmets 中所述,您应该为此使用矢量的内置功能。但是:

    当您reserve() 元素时,向量将为(至少?)这么多元素分配足够的空间。向量中不存在元素,但内存已准备好使用。这可能会加速push_back(),因为内存已经分配。

    当您resize() 向量时,它会为这些元素分配足够的空间,还会将它们添加到向量中

    因此,如果将向量的大小调整为 100,则可以访问 0 - 99 的元素,但如果保留 100 个元素,它们还没有插入,只是可以使用。

    你想要的是这样的:

    vec2.reserve( vec1.size() );
    copy(vec1.begin(), vec1.end(), std::back_inserter(vec2));
    

    std::back_inserter 定义在&lt;iterator&gt;

    【讨论】:

    • 嘿,是的。一开始我也被这种差异所吸引。
    • 尤里卡 - 有效。不仅在发布的测试应用程序上,而且在我遇到的更复杂的问题应用程序上。我避免使用 resize() 因为它添加了我不打算添加的元素。感谢您的教育。
    • 你真的应该改用vec2.assignvec2.insert...它们更优化了。
    • 由于某种原因 vec2.begin() 无法编译,但 vec2 可以正常工作
    【解决方案3】:

    为什么不:vec2 = vec1;

    【讨论】:

    • 是的,这很好 :D 但它确实说明了向量的 resize() 和 reserve() 之间的区别,这让我绊倒了几个小时。
    • 这对我也有帮助,虽然不是我所要求的,但我不知道复制 ctor。谢谢。
    • 简洁优雅。奇怪的是,这么简单的事情在 C++ 中从来都不是显而易见的。
    【解决方案4】:

    在我看来,最简单的方法是使用std::vector::insert 方法:

    v2.insert(v2.end(), v1.begin(), v1.end());
    

    (见std::vector::insert

    【讨论】:

      【解决方案5】:

      将保留更改为 resize():

      vec2.resize(vec1.size(), '\0');
      copy(vec1.begin(), vec1.end(), vec2.begin());
      

      我相信这是您需要的解决方法。

      我不能给你一个很好的区别描述,但基本上 reserve() 确保你有足够的空间,而 resize() 实际上在那里插入了一些东西。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-03-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多