【问题标题】:How to efficiently insert a pair in std::vector?如何有效地在 std::vector 中插入一对?
【发布时间】:2018-10-19 22:59:59
【问题描述】:

我有一个std::vector<std::pair<...>> 并想有效地修改它们:

vector<pair<int, int>> vec;
vec.emplace_back(4, 5);
vec.emplace_back(6, 7);

// Now I want to set the first pair in the vector.
vec[0] = make_pair(10, 10);

据我了解,我们有

  1. 临时对由make_pair 构造。这需要 2 份 ints。
  2. 接下来调用pair&lt;int,int&gt;&amp; operator=( pair&lt;int,int&gt;&amp;&amp; other ),它在pair 中的两个ints 上调用std::move。这需要 2 份 ints。

因此我们有 4 个整数副本!

但是在Vector 中修改pair 应该需要ints 的2 个副本。 emplace_back 似乎是我需要的,但它只在向量的末尾进行就地构造,而不是在任何其他索引处。

当然可以

vec[0].first = 10;
vec[0].second = 10;

但这考虑了pair的内部结构,我想省略。

如何更有效地编写代码(没有ints 的冗余副本)?

【问题讨论】:

  • 一对整数的移动将与一对整数的副本具有相同的性能。 FWIW。
  • 除非你能衡量一个问题,否则我不会担心几个整数。这是在一个巨大的循环中吗?
  • 仅供参考,std::pair 有一个将两个值作为输入的构造函数,因此您可以在调用 emplace_back() 时省略 make_pair()vec.emplace_back(4, 5);
  • 我想这段代码在性能关键循环中工作。 emplace_back 在末尾添加了一个元素,但是我需要在中间修改一个元素。

标签: c++ int std move stdvector


【解决方案1】:

启用编译器优化,瞧,它们完全一样:https://godbolt.org/z/Nwb_y0

GCC 8 生成的程序集是:

    mov     rax, QWORD PTR [rdi]
    mov     DWORD PTR [rax], esi
    mov     DWORD PTR [rax+4], edx

如您所见,整数只存储一次,没有多余的副本。

如果您使用-O1 而不是-O2-O3 进行编译,那么对于没有make_pair 的“更简单”版本,代码实际上更糟糕:它从向量中加载地址两次。所以make_pair 版本在-O1 上更好,在更高级别的优化上相同。

【讨论】:

  • 谢谢! godbolt.org 是探索编译代码的好地方!
猜你喜欢
  • 1970-01-01
  • 2013-08-18
  • 2018-05-31
  • 2014-08-10
  • 1970-01-01
  • 2019-05-22
  • 2020-11-22
  • 2016-02-04
  • 1970-01-01
相关资源
最近更新 更多