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

Is shrink_to_fit the proper way of reducing the capacity a `std::vector` to its size?(shrink_to_fit 是将 `std::vector` 的容量减少到其大小的正确方法吗?)

本文介绍了shrink_to_fit 是将 `std::vector` 的容量减少到其大小的正确方法吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 C++11 中引入 shr​​ink_to_fit 以补充某些 STL 容器(例如,std::vectorstd::dequestd::string).

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

Synopsizing,其主要功能是请求关联的容器,减少其容量以适应其大小.然而,这个请求是非约束性的,容器实现可以自由地优化,否则向量的容量大于其大小.

Synopsizing, its main functionality is to request the container that is associated to, to reduce its capacity to fit its size. However, this request is non-binding, and the container implementation is free to optimize otherwise and leave the vector with a capacity greater than its size.

此外,在之前的 SO 问题中,不鼓励 OP 使用 shr​​ink_to_fit 将他的 std::vector 的容量减少到其大小.不这样做的原因如下:

Furthermore, in a previous SO question the OP was discouraged from using shrink_to_fit to reduce the capacity of his std::vector to its size. The reasons not to do so are quoted below:

shr​​ink_to_fit 什么都不做,或者它会给你缓存局部性问题,它是 O(n)执行(因为您必须将每个项目复制到他们新的、较小的家中).通常将松弛留在内存中会更便宜.@Massa

shrink_to_fit does nothing or it gives you cache locality issues and it's O(n) to execute (since you have to copy each item to their new, smaller home). Usually it's cheaper to leave the slack in memory. @Massa

有人可以回答以下问题吗:

Could someone be so kind as to address the following questions:

  • 引文中的论点是否成立?
  • 如果是,将 STL 容器的容量缩小到其大小的正确方法是什么(至少对于 std::vector).
  • 如果有更好的方法来缩小容器,那么 shr​​ink_to_fit 到底存在的原因是什么?
  • Do the arguments in the quotation hold?
  • If yes, what's the proper way of shrinking an STL container's capacity to its size (at least for std::vector).
  • And if there's a better way to shrink a container, what's the reason for the existence of shrink_to_fit after-all?

推荐答案

引文中的论点成立吗?

Do the arguments in the quotation hold?

量一量你就知道了.你的内存受限吗?你能预先找出正确的尺寸吗?保留比事后缩小更有效.总的来说,我倾向于同意这样一个前提,即大多数用途可能适用于 slack.

Measure and you will know. Are you constrained in memory? Can you figure out the correct size up front? It will be more efficient to reserve than it will be to shrink after the fact. In general I am inclined to agree on the premise that most uses are probably fine with the slack.

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

If yes, what's the proper way of shrinking an STL container's capacity to its size (at least for std::vector).

该注释不仅适用于 shr​​ink_to_fit,还适用于任何其他缩小方式.鉴于您无法 realloc 就地,它涉及获取不同的内存块并复制到那里,无论您使用什么机制进行收缩.

The comment does not only apply to shrink_to_fit, but to any other way of shrinking. Given that you cannot realloc in place, it involves acquiring a different chunk of memory and copying over there regardless of what mechanism you use for shrinking.

如果有更好的方法来缩小容器,那么shrink_to_fit 存在的原因到底是什么?

And if there's a better way to shrink a container, what's the reason for the existence of shrink_to_fit after-all?

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

The request is non-binding, but the alternatives don't have better guarantees. The question is whether shrinking makes sense: if it does, then it makes sense to provide a shrink_to_fit operation that can take advantage of the fact that the objects are being moved to a new location. I.e., if the type T has a noexcept(true) move constructor, it will allocate the new memory and move the elements.

虽然您可以在外部实现相同的功能,但此接口简化了操作.相当于 C++03 中的 shr​​ink_to_fit 应该是:

While you can achieve the same externally, this interface simplifies the operation. The equivalent to shrink_to_fit in C++03 would have been:

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

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

But the problem with this approach is that when the copy is done to the temporary it does not know that current is going to be replaced, there is nothing that tells the library that it can move the held objects. Note that using std::move(current) would not achieve the desired effect as it would move the whole buffer, maintaining the same capacity().

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

Implementing this externally would be a bit more cumbersome:

{
   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 条件正确……这可能不是您每次想要此操作时都想写的内容.

Assuming that I got the if condition right... which is probably not what you want to write every time that you want this operation.

这篇关于shrink_to_fit 是将 `std::vector` 的容量减少到其大小的正确方法吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本文标题为:shrink_to_fit 是将 `std::vector` 的容量减少到其大小的正确方法吗?

基础教程推荐