是shrink_to_fit正确的方法减少容量的`std :: vector`到它的大小?(Is shrink_to_fit the proper way of reducing the capaci
In C++11 shrink_to_fit was introduce to complement certain STL containers (e.g., std::vector, std::deque, std::string).
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.
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:
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:
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?
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 is to shrink after the fact. In general I am inclined to agree on the premise that most uses are probably fine with the slack.
If yes, what's the proper way of shrinking an STL container's capacity to its size (at least for std::vector).
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.
And if there's a better way to shrink a container, what's the reason for the existence of shrink_to_fit after-all?
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 shring_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.
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);
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);
}
Assuming that I got the if condition right... which is probably not what you want to write every time that you want this operation.
在C ++ 11 shrink_to_fit 中介绍了补充某些STL容器(例如, std :: vector std :: deque , std :: string )。
复制,其主要功能是请求与之关联的容器,减小其容量以适应其大小。但是,此请求不具有约束力,并且容器实施可以自由优化,并使向量的容量大于其大小。
此外,在以前的SO问题中,OP不鼓励使用 shrink_to_fit 减少他的 std :: vector 到其大小。不这样做的原因如下:
shrink_to_fit 没有或它给你缓存局部性问题,它的O(n)到
执行(因为你必须将每个项目复制到他们新的,较小的家)。
通常,在内存中留下松弛部分更便宜。 @Massa
有人可以这样讨论以下问题:
在报价中保留参数吗?
如果是,将STL容器的容量缩小到其大小是正确的方法(至少 std :: vector )。
如果有一个更好的收缩容器的方法,存在 shrink_to_fit 后的原因是什么?
解决方案
p>
测量,你就会知道。你在记忆中受限吗?你能找出正确的大小吗?在事实之后保留比收缩更有效。一般来说,我倾向于同意这样一个前提,即多数用途可能与闲置很好。
如果是,将STL容器的容量缩小到其大小(至少对于std :: vector)。
注释不仅适用于 shrink_to_fit ,但是任何其他收缩的方式。考虑到你不能 realloc 到位,它涉及获取一个不同的内存块,并在那里复制,无论你使用什么机制收缩。
如果有一个更好的方法收缩一个容器,shrink_to_fit后存在的原因是什么?
请求是非绑定的,但是替代方案没有更好的保证。问题是是否缩小是有意义的,如果是这样,那么提供 shring_to_fit 操作是有意义的,可以利用这一事实:正在将对象移动到新位置。也就是说如果类型 T 有一个 noexcept(true)移动构造函数,它将分配新的内存并移动元素。
虽然您可以在外部实现相同的操作,但该界面简化了操作。相当于C ++ 03中的 shrink_to_fit 应该是:
std :: vector< T>(current).swap(current);
但是这种方法的问题是,当复制到临时文件时,它不知道 current 将被替换,没有什么告诉库,它可以移动持有的对象。注意,使用 std :: move(current)不会实现所需的效果,因为它会移动整个缓冲区,保持相同 capacity()。
在外部实现会更加繁琐:
{
std :: vector< T>复制;
if(noexcept(T(std :: move(declat< 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条件右...这可能不是什么你想每次都想写这个操作。
