C ++向量的insert和push_back差异


C++ vector's insert & push_back difference

我想知道vectorpush_backinsert函数之间的区别是什么。

有结构上的差异吗?

在性能上有很大的不同吗?


最大的区别在于它们的功能。 push_back总是在vector的末尾放置一个新元素,并且insert允许您选择新元素的位置。这会影响性能。 vector元素仅在需要增加其长度时才在内存中移动,因为为其分配的内存太少了。另一方面,insert强制将所有元素移动到新元素的选定位置之后。您只需要为此放置一个位置。这就是为什么insert效率通常可能不及push_back的原因。


功能具有不同的用途。 vector::insert允许您在vector中的指定位置插入对象,而vector::push_back只是将对象粘在末端。请参见以下示例:

1
2
3
4
5
using namespace std;
vector<int> v = {1, 3, 4};
v.insert(next(begin(v)), 2);
v.push_back(5);
// v now contains {1, 2, 3, 4, 5}

您可以使用insertv.insert(v.end(), value)来执行与push_back相同的任务。


除了push_back(x)的功能与insert(x, end())相同(也许具有更好的性能)外,还需要了解以下有关这些功能的几件事:

  • push_back仅存在于BackInsertionSequence容器上-因此,例如,它不存在于set上。不能这样做是因为push_back()会始终将其添加到结尾。
  • 一些容器也可以满足FrontInsertionSequence并且具有push_frontdeque可以满足,但vector不能满足。
  • insert(x, ITERATOR)来自InsertionSequence,这对于setvector是通用的。这样,您可以将setvector用作多次插入的目标。但是,set另外具有insert(x),它实际上具有相同的作用(在set中的第一次插入仅意味着通过从不同的迭代器开始加快搜索适当位置的功能-在这种情况下不使用此功能)。
  • 关于最后一种情况,请注意,如果要在循环中添加元素,则执行container.push_back(x)container.insert(x, container.end())将会有效地完成相同的操作。但是,如果先获得此container.end()然后在整个循环中使用它,那将不是正确的。

    例如,您可能会冒险以下代码:

    1
    2
    3
    auto pe = v.end();
    for (auto& s: a)
        v.insert(pe, v);

    这将以相反的顺序有效地将整个a复制到v向量中,只有在您有幸没有重新分配向量进行扩展时(可以通过首先调用reserve()来防止这种情况);如果您不太幸运,则会得到所谓的UndefinedBehavior(tm)。从理论上讲,这是不允许的,因为每次添加新元素时,矢量的迭代器都被视为无效。

    如果您这样做:

    1
    copy(a.begin(), a.end(), back_inserter(v);

    它将按原始顺序在v的末尾复制a,这不存在迭代器无效的风险。

    [编辑]我以前使这段代码看起来是这样,这是一个错误,因为inserter实际上保持了迭代器的有效性和先进性:

    1
    copy(a.begin(), a.end(), inserter(v, v.end());

    因此,此代码还将以原始顺序添加所有元素,而没有任何风险。