【问题标题】:Optimizing erase from the end of vector into resize将矢量末尾的擦除优化为调整大小
【发布时间】:2016-06-01 18:18:21
【问题描述】:

编译器优化这段代码是否合法且有可能:

std::vector<T> my_vec(10);
//some code
my_vec.erase(my_vec.begin()+5,my_vec.end());

进入:

std::vector<T> my_vec(10);
//some code
my_vec.resize(5);

我之所以问,是因为我总是读到 std::vector::resize 从末尾擦除时比 std::vector::erase 更可取。但是,我发现std::vector::erase 更具可读性。

【问题讨论】:

  • 您认为哪里更可取,理由是什么?
  • 我在一些 SO 答案中看到它作为旁注。我不记得原因是什么,或者是否提到了原因。也许我应该先问一下它是否真的更好:)
  • @HumamHelfawi:不,为什么认为erase看起来更好?
  • 这两个调用几乎肯定会做同样的事情 - 所以你喜欢哪个就是你喜欢的那个。
  • @Barry 不,事实并非如此。

标签: c++ c++11 vector compiler-optimization


【解决方案1】:

类型要求不同。

  • vector::resize(单参数版本)不需要MoveAssignable,但需要DefaultInsertableMoveInsertable,因为它也可以用来扩展容器。

  • vector::erase 是相反的;它需要MoveAssignable 而不是其他的,因为它可以用来在中间擦除。

  • vector::pop_back 不需要上述任何一项,但一次只弹出一个元素,因此您必须多次调用它。

在任何合理的实施中都不应存在可察觉的性能差异。

【讨论】:

  • 非常有帮助。谢谢
  • 拥有std::vector::shrink_by 的理由,它与pop_back 匹配。我怀疑pop_back 的循环可能比shrink_by 的效率低,但可能不是:如果对象的析构函数之一抛出,会发生什么?
  • @Yakk UB,像往常一样。在标准库中使用抛出析构函数是 UB。
【解决方案2】:

此类优化是否合法且可能发生?是的。规范中没有任何内容禁止将一种转换为另一种。因此,从 vector 末尾开始的 erase 操作按照缩小的 resize 的胆量来实现是合法的。

【讨论】:

  • 等等,resize在哪里指定倒序?
  • @T.C.:是的,我也觉得这很奇怪。它是根据pop_back 调用的序列定义的:“如果sz &lt;= size(),相当于调用pop_back()size() - sz 次。
  • 哦,that was a defect。也只影响 C++14。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多