shrink_to_fit 是将“std::vector”的容量减小到其大小的正确方法吗?

新手上路,请多包涵

In C++11 shrink_to_fit was introduce to complement certain STL containers (eg, std::vector , std::deque , std::string ).

概括地说,它的主要功能是请求关联的容器, 以减少其容量以适应其大小。但是,此 请求是非绑定 的,容器实现可以自由优化,并使向量的容量大于其大小。

此外,在之前的 SO question 中,不鼓励 OP 使用 shrink_to_fit 将他的 std::vector 的容量减小到其大小。不这样做的原因如下:

shrink_to_fit 什么都不做,或者它会给你缓存位置问题,并且执行时间为 O(n)(因为你必须将每个项目复制到它们新的、更小的家中)。通常,将松弛的内存留在内存中会更便宜。 @马萨

有人可以很好地解决以下问题:

  • 引文中的论点成立吗?
  • 如果是,将 STL 容器的容量缩小到其大小的正确方法是什么(至少对于 std::vector )。
  • 如果有更好的方法来缩小容器,那么到底存在 shrink_to_fit 的原因是什么?

原文由 101010 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.8k
1 个回答

引文中的论点成立吗?

测量一下,你就会知道。你记忆力有限吗?你能预先确定正确的尺寸吗? reserve 比事后 收缩 更有效。总的来说,我倾向于同意大多数用途可能与松弛无关的前提。

如果是,那么将 STL 容器的容量缩小到其大小的正确方法是什么(至少对于 std::vector 而言)。

该评论不仅适用于 shrink_to_fit ,还适用于任何其他收缩方式。鉴于您不能 realloc 到位,它涉及获取不同的内存块并在那里复制,无论您使用什么机制进行收缩。

如果有更好的方法来缩小容器,那么到底为什么会存在 shrink_to_fit 呢?

该请求不具有约束力,但替代方案没有更好的保证。问题是 缩小 是否有意义:如果有,那么提供一个 shrink_to_fit 操作可以利用对象被 移动 到新位置的事实是有意义的。即,如果类型 T 具有 noexcept(true) 移动构造函数,它将分配新内存并移动元素。

虽然您可以在外部实现相同的功能,但此界面简化了操作。与 shrink_to_fit 在 C++03 中的等价物是:

 std::vector<T>(current).swap(current);

但是这种方法的问题是,当复制到临时文件时,它不知道 current 将被替换,没有任何东西告诉库它 可以 移动持有的对象。请注意,使用 std::move(current) 不会达到预期的效果,因为它会 移动 整个缓冲区,保持相同的 capacity()

在外部实现这个会有点麻烦:

 {
   std::vector<T> copy;
   if (noexcept(T(std::move(declval<T>())))) {
      copy.assign(std::make_move_iterator(current.begin()),
                  std::make_move_iterator(current.end()));
   } else {
      copy.assign(current.begin(), current.end());
   }
   copy.swap(current);
}

假设我的 if 条件是正确的……这可能不是你每次想要这个操作时都想写的。

原文由 David Rodríguez - dribeas 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题