101*_*010 24 c++ stl vector c++11
在C++ 11 shrink_to_fit是引入补充某些STL容器(例如,std::vector,std::deque,std::string).
Synopsizing,其主要功能是请求与之关联的容器,以减少其容量以适应其大小.但是,此请求是非绑定的,并且容器实现可以自由地进行优化,并使向量的容量大于其大小.
此外,在之前的SO问题中,OP不鼓励使用它shrink_to_fit来减小其容量std::vector.不这样做的理由如下:
shrink_to_fit什么都不做,或者它给你缓存局部性问题,并且执行O(n)(因为你必须将每个项目复制到他们新的较小的家庭).通常,将松弛留在内存中会更便宜.@Massa
有人可以如此善意地解决以下问题:
std::vector).shrink_to_fit?Dav*_*eas 15
报价中的参数是否成立?
措施,你会知道.你是否受限于记忆?你能预先确定正确的尺寸吗?事后收缩reserve比收缩更有效率.总的来说,我倾向于同意这样的前提,即大多数用途可能都很好.
如果是,那么将STL容器的容量缩小到其大小的正确方法是什么(至少对于std :: vector).
评论不仅适用于shrink_to_fit,而且适用于任何其他缩小方式.鉴于你不能realloc到位,它涉及获取不同的内存块并在那里进行复制,无论你使用什么机制进行收缩.
如果有一个更好的方法来缩小容器,那么后来存在shrink_to_fit的原因是什么?
该请求不具有约束力,但替代方案没有更好的保证.问题是缩小是否有意义,如果确实如此,那么提供一个shrink_to_fit可以利用对象被移动到新位置这一事实的操作是有意义的.即如果类型T具有noexcept(true)移动构造函数,它将分配新内存并移动元素.
虽然您可以在外部实现相同的功能,但此界面可简化操作.与shrink_to_fitC++ 03相同的是:
std::vector<T>(current).swap(current);
Run Code Online (Sandbox Code Playgroud)
但是这种方法的问题在于,当复制完成到临时时它不知道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);
}
Run Code Online (Sandbox Code Playgroud)
假设我得到if条件正确...这可能不是你想要在每次想要这个操作时写的东西.
Mas*_*ssa 14
- 论证会持有吗?
由于争论最初是我的,所以不要介意我一个接一个地为他们辩护:
要么shrink_to_fit什么都不做(......)
正如所提到的那样,标准说(很多次,但在vector第23.3.7.3节的情况下......)请求是非绑定的,以允许优化的实现范围.这意味着实现可以定义shrink_to_fit为无操作.
(...)或它给你缓存局部性问题
在这种情况下shrink_to_fit是不作为无操作实现的,你必须分配容量新的基础容器size(),副本(或,在最好的情况下,移动)构建所有N = size()从旧的新项目,销毁所有旧的(在移动的情况下,这应该被优化,但是这可能涉及在旧容器上再次循环)然后破坏旧容器本身.libstdc++-4.9正如David Rodriguez所描述的那样,这完成了
_Tp(__make_move_if_noexcept_iterator(__c.begin()),
__make_move_if_noexcept_iterator(__c.end()),
__c.get_allocator()).swap(__c);
Run Code Online (Sandbox Code Playgroud)
并且libc++-3.5通过其中的函数__alloc_traits大致相同.
哦,并且一个实现绝对不能依赖realloc(即使它malloc在内部::operator new使用其内存分配),因为realloc,如果它不能就地收缩,将要么单独留下内存(无操作情况)或进行按位复制(并且错过)重新调整正确的C++复制/移动构造函数会给出的指针等的机会.
当然,可以编写一个可收缩的内存分配器,并在其向量的构造函数中使用它.
在向量大于高速缓存行的简单情况下,所有这些移动都会对高速缓存施加压力.
它是O(n)
如果n = size(),我认为它已经建立在上面,至少,你必须做一个n大小的分配,n复制或移动结构,n破坏和一个old_capacity大小的释放.
通常只是将松弛留在记忆中更便宜
显然,除非你真的要求免费内存(在这种情况下,将数据保存到磁盘并在以后按需重新加载它可能更明智......)
- 如果是,那么将STL容器的容量缩小到其大小的正确方法是什么(至少对于std :: vector).
正确的方法仍然是shrink_to_fit......你必须要么不依赖它,要么非常了解你的实施!
- 如果有一个更好的方法来缩小容器,那么后来存在shrink_to_fit的原因是什么?
没有更好的方法,但存在的原因shrink_to_fit是,AFAICT,有时你的程序可能会感到记忆压力,这是一种治疗它的方法.不是很好的方式,但仍然.
HTH!