82

我想知道vector'spush_backinsertfunctions 之间有什么区别。

是否存在结构差异?

性能差异真的很大吗?

4

4 回答 4

97

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

于 2012-11-10T17:41:42.273 回答
32

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

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}

您可以使用insert来执行与 相同的push_back工作v.insert(v.end(), value)

于 2012-11-10T17:41:52.560 回答
10

除了事实上,这push_back(x)insert(x, end())(可能性能稍好)相同,关于这些功能还有几件重要的事情需要了解:

  1. push_back仅存在于BackInsertionSequence容器上 - 例如,它不存在于set. 它不能因为push_back()授予你它总是会在最后添加。
  2. 一些容器也可以满足FrontInsertionSequence并且他们有push_front. 满足deque,但不满足vector
  3. insert(x, ITERATOR)是来自,这对于和InsertionSequence很常见。这样,您可以使用其中一个或作为多个插入的目标。但是,has 另外,它实际上做了同样的事情(第一次插入仅意味着通过从不同的迭代器开始来加速搜索适当的位置 - 在这种情况下未使用此功能)。setvectorsetvectorsetinsert(x)set

请注意最后一种情况,如果您要在循环中添加元素,那么做container.push_back(x)并且container.insert(x, container.end())将有效地做同样的事情。container.end()然而,如果你先得到它然后在整个循环中使用它,这将不是真的。

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

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

这将有效地以相反的顺序将整个复制av向量中,并且只有当您足够幸运没有为扩展重新分配向量时(您可以通过先调用来防止这种情况);如果你不是那么幸运,你会得到所谓的 UndefinedBehavior(tm)。理论上这是不允许的,因为每次添加新元素时,vector 的迭代器都被认为是无效的。reserve()

如果你这样做:

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

它将在原始顺序a的末尾复制v,这不会带来迭代器失效的风险。

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

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

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

于 2016-10-05T10:10:14.887 回答
1

我在上面的任何评论中都没有看到它,但重要的是要知道:

如果我们希望向给定向量添加新元素并且向量的新大小(包括新元素)超过当前向量容量,则会导致分配的存储空间自动重新分配。因为内存分配是我们希望最小化的一个动作,它将以相同的方式增加push_back 和 insert中的容量(对于具有 n 元素的向量将增加大约 n/2)。

因此,就内存效率而言,可以肯定地说,使用你最喜欢的东西。例如:

std::vector<int> test_Insert = { 1,2,3,4,5,6,7 };
std::vector<int> test_Push_Back = { 1,2,3,4,5,6,7 };

std::cout << test_Insert.capacity() << std::endl;
std::cout << test_Push_Back.capacity() << std::endl;

test_Insert.push_back(8);
test_Push_Back.insert(test_Push_Back.end(), 8);

std::cout << test_Insert.capacity() << std::endl;
std::cout << test_Push_Back.capacity() << std::endl;

此代码将打印:

7

7

10

10

于 2022-02-13T07:58:00.583 回答