【问题标题】:How to move the later half of a vector into another vector?如何将一个向量的后半部分移动到另一个向量中?
【发布时间】:2012-08-09 22:52:22
【问题描述】:

我有一个向量,我想使用 STL 算法有效地将向量的后半部分分解为另一个向量。这是我看到的一种方法,但希望有更有效和简洁的答案,或者至少是使用 stl 算法的答案:

std::vector<Entry> &entries = someFunction();
int numEntries = entries.size();

// Assume numEntries is greater than or equal to 2.

std::vector<Entry> secondEntries;
std::vector<Entry>::iterator halfway = entries.begin() + numEntries / 2;
std::vector<Entry>::iterator endItr  = entries.end() 

// Copy the second half of the first vector in the second vector:
secondEntries.insert(secondEntries.end(), halfway, endItr);

// Remove the copied entries from the first vector:
entries.erase(halfway, endItr);

【问题讨论】:

  • 唯一的优化是为secondEntries 保留足够的大小,这样就不需要重新分配。除此之外,还有什么比简单地复制元素更有效?
  • @mfontanini vector 的插入不是已经为随机访问迭代器做到这一点了吗?
  • 顺便说一句,您可以使用插入数据创建向量std::vector&lt;Entry&gt; secondEntries(halfway, endItr);
  • @MarkB 你是对的。好吧,那基本上没有优化xD

标签: c++ insert stdvector erase


【解决方案1】:

还有其他几种方法可以执行此任务,例如使用复制算法和插入迭代器。

但是由于向量容器的性质,这些动作的算法复杂度总是 O(n)。 Vector 不是一个允许在 O(1)(常数)时间内将大块数据从一个容器移动到另一个容器的列表。根据特定的 STL 实现,一种方法可能比另一种方法好 10-20%,但不太可能超过此值。

如果您的容器的数据类型允许移动语义,并且您有这些语言功能可用,这肯定会有所帮助。但这更多是关于在容器中处理数据对象而不是容器本身。

【讨论】:

    【解决方案2】:

    退后一步,请记住确保您使用的是具有自己算法的迭代器,而不是(必然)容器。所以如果你有这个:

    void foo(const std::vector<Entry>& v) { /* ... */ }
    

    现在你陷入了这种情况:

    std::vector<Entry> entries = someFunction();
    
    // have to split entries! make more containers? :(
    foo(first_half(entries));
    foo(second_half(entries));
    

    考虑使用迭代器:

    // or a template, if it doesn't hurt
    void foo(std::vector<Entry>::const_iterator first, 
             std::vector<Entry>::const_iterator second) { /* ... */ }
    

    所以现在你表示范围而不是容器:

    std::vector<Entry> entries = someFunction();
    
    // easy to split entries! :)
    auto middle = entries.begin() + entries.size() / 2;
    foo(entries.begin(), middle);
    foo(middle + 1, entries.end());
    

    这限制了您进行的不必要容器和分配的数量。


    除此之外,在 C++11 中您可以这样做(其余部分相同):

    // *Move* the second half of the first vector in the second vector:           
    secondEntries.insert(secondEntries.end(),
                            std::make_move_iterator(halfway),
                            std::make_move_iterator(endItr));
    

    如果Entry 有一个移动构造函数,move_iterator 适配器将确保在插入期间使用它(如果它没有进行正常复制)。在 C++03 中,你所拥有的可能是最好的。

    【讨论】:

      【解决方案3】:

      如果您可以访问 c++11 编译器和可移动对象,std::move 可以做得更好。

      请注意,您仍然需要从第一个向量中删除它们。

      【讨论】:

        猜你喜欢
        • 2011-08-13
        • 2018-07-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-10-13
        • 1970-01-01
        相关资源
        最近更新 更多