如何减少 std::vector 的容量
有没有办法减少向量的容量?
我的代码将值插入向量(事先不知道它们的数量),并且 完成后,向量仅用于读取操作。
我想我可以创建一个新向量,用大小和副本执行 .reseve() 项目,但我不太喜欢额外的复制操作。
PS:我不关心便携式解决方案,只要它适用于 gcc 即可。
Is there a way to reduce the capacity of a vector ?
My code inserts values into a vector (not knowing their number beforehand), and
when this finishes, the vectors are used only for read operations.
I guess I could create a new vector, do a .reseve() with the size and copy
the items, but I don't really like the extra copy operation.
PS: I don't care for a portable solution, as long as it works for gcc.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
使用 C++11,您可以调用成员函数
shrink_to_fit()
。 标准草案第 23.2.6.2 节说:With C++11, you can call the member function
shrink_to_fit()
. The draft standard section 23.2.6.2 says:与另一个向量交换内容会交换容量。
Swap()只会改变内部数据结构。
Swapping the contents with another vector swaps the capacity.
Swap() would only change the internal data structure.
去看看 Scott Meyers effective STL item 17。
基本上你不能直接减少
std::vector
的存储大小。resize()
和reseve()
永远不会减少容器的实际内存占用。 “技巧”是创建一个大小合适的新容器,复制数据并将其与当前容器交换。 如果我们想清除一个容器,这很简单:如果我们必须复制数据,那么我们需要进行复制:
它的作用是使用旧向量中的数据创建一个新向量,执行复制将在任何具有您所需效果的操作中都需要。 然后调用
swap()
将仅交换对象之间的内部缓冲区。 在该行的末尾,创建的临时向量被删除,但它具有旧向量的内容,而旧向量具有新副本的内容,这正是我们需要的大小。Go look at Scott Meyers Effective STL item 17.
Basically you can't directly reduce the storage size of a
std::vector
.resize()
andreseve()
will never reduce the actually memory footprint of a container. The "trick" is to create a new container of the right size, copy the data and swap that with the current container. If we would like to clear a container out this is simply:If we have to copy the data over then we need to do the copy:
What this does is creates a new vector with the data from the old one, doing the copy that would be required in any operation that has the effect you need. Then calling
swap()
will just swap the internal buffers between the objects. At the end of the line the temporary vector that was created is deleted, but it has the guts from the old vector and the old vector has the guts from the new copy that is the exact size we need.惯用的解决方案是与新构建的向量进行交换。
编辑:我读错了问题。 上面的代码将清除向量。 OP希望保持元素不变,只需将
capacity()
缩小到size()
。很难说 aJ 的代码是否能做到这一点。 我怀疑是否有便携式解决方案。 对于
gcc
,您必须查看它们的vector
的特定实现。编辑:所以我查看了 libstdc++ 实现。 看来aJ的解决方案确实有效。
请参阅源代码,第 232 行。
The idiomatic solution is to swap with a newly constructed vector.
Edit: I misread the question. The code above will clear the vector. OP wants to keep the elements untouched, only shrink
capacity()
tosize()
.It is difficult to say if aJ's code will do that. I doubt there's portable solution. For
gcc
, you'll have to take a look at their particular implementation ofvector
.edit: So I've peeked at libstdc++ implementation. It seems that aJ's solution will indeed work.
See the source, line 232.
不,您无法在不进行复制的情况下减少向量的容量。 但是,您可以通过检查capacity()并在每次插入内容时调用reserve()来控制新分配的增长量。 std::vector 的默认行为是每次需要新容量时将其容量增加 2 倍。 您可以通过自己的神奇比率来增长它:
如果您喜欢一些黑客技术,您可以随时传入自己的分配器并执行任何您需要执行的操作来回收未使用的容量。
No, you cannot reduce the capacity of a vector without copying. However, you can control how much new allocation growth by checking capacity() and call reserve() every time you insert something. The default behavior for std::vector is to grow its capacity by a factor of 2 every time new capacity is needed. You can growth it by your own magic ratio:
If you're into a bit hacky techniques, you can always pass in your own allocator and do whatever you need to do to reclaim the unused capacity.
我并不是说 GCC 无法在没有副本的情况下提供某种方法来执行您想要的操作,但实现起来会很棘手(我认为),因为向量需要使用
Allocator
对象来分配并释放内存,并且Allocator
的接口不包含reallocate()
方法。 我不认为这是不可能做到的,但可能会很棘手。I'm not saying that GCC couldn't have some method for doing what you want without a copy, but it would be tricky to implement (I think) because vectors need to use an
Allocator
object to allocate and deallocate memory, and the interface for anAllocator
doesn't include areallocate()
method. I don't think it would be impossible to do, but it might be tricky.如果您担心向量的开销,那么也许您应该考虑使用另一种类型的数据结构。 您提到,一旦代码完成向量初始化,它就会成为只读进程。 我建议使用开放式数组,该数组将允许程序在编译时决定其容量。 或者也许链接列表更适合您的需求。
让我知道我是否完全误解了你的意思。
-UBcse
If you're worried about about the overhead of your vector then maybe you should be looking to using another type of data structure. You mentioned that once your code is done initializing the vector it becomes a read only process. I would suggest going with an open ended array that will allow the program to decide its capacity at compile time. Or perhaps a linked list would be more suitable to your needs.
Lemme know if I completely misunderstood what you were getting at.
-UBcse
老线程,我知道,但以防万一将来有人看到这个.. C++11中有shrink_to_fit(),但由于它是一个非绑定请求,因此行为将取决于其实现。
请参阅:http://en.cppreference.com/w/cpp/container/vector /shrink_to_fit
Old thread, I know, but in case anyone is viewing this in the future.. there's shrink_to_fit() in C++11 but since it is a non-binding request, the behaviour will depend on its implementation.
See: http://en.cppreference.com/w/cpp/container/vector/shrink_to_fit
我不是 C++ 专家,但似乎这个 解决方案有效(至少用 g++ 编译它可以):
I'm not an expert in C++,but it seems this solution works(atleast compiling it with g++ does):
这也有效:
在线尝试!
它调用
&&
重载=
运算符,它进行移动,swap() 使用相同的重载。This also works:
Try it online!
It calls
&&
overload of=
operator, which does moving, same overload is used by swap().获取 Scott Myers 所著的“Effective STL”一书。 它有一个完整的项目只是减少向量的容量。
Get the "Effective STL" book by Scott Myers. It has a complete item jus on reducing vector's capacity.