如何减少 std::vector 的容量

发布于 2024-07-26 15:36:55 字数 177 浏览 6 评论 0原文

有没有办法减少向量的容量?

我的代码将值插入向量(事先不知道它们的数量),并且 完成后,向量仅用于读取操作。

我想我可以创建一个新向量,用大小和副本执行 .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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

友欢 2024-08-02 15:36:55

使用 C++11,您可以调用成员函数 shr​​ink_to_fit()标准草案第 23.2.6.2 节说:

shr​​ink_to_fit 是一个非绑定请求
capacity() 减少到 size()[注意:该请求不具有约束力
允许纬度
特定于实现的优化。
——尾注]

With C++11, you can call the member function shrink_to_fit(). The draft standard section 23.2.6.2 says:

shrink_to_fit is a non-binding request
to reduce capacity() to size(). [Note: The request is non-binding to
allow latitude for
implementation-specific optimizations.
—end note]

╰ゝ天使的微笑 2024-08-02 15:36:55
std::vector<T>(v).swap(v);

与另一个向量交换内容会交换容量。

  std::vector<T>(v).swap(v); ==> is equivalent to 

 std::vector<T> tmp(v);    // copy elements into a temporary vector
         v.swap(tmp);              // swap internal vector data

Swap()只会改变内部数据结构。

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

Swapping the contents with another vector swaps the capacity.

  std::vector<T>(v).swap(v); ==> is equivalent to 

 std::vector<T> tmp(v);    // copy elements into a temporary vector
         v.swap(tmp);              // swap internal vector data

Swap() would only change the internal data structure.

稀香 2024-08-02 15:36:55

去看看 Scott Meyers effective STL item 17。

基本上你不能直接减少 std::vector 的存储大小。 resize()reseve() 永远不会减少容器的实际内存占用。 “技巧”是创建一个大小合适的新容器,复制数据并将其与当前容器交换。 如果我们想清除一个容器,这很简单:

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

如果我们必须复制数据,那么我们需要进行复制:

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

它的作用是使用旧向量中的数据创建一个新向量,执行复制将在任何具有您所需效果的操作中都需要。 然后调用 swap() 将仅交换对象之间的内部缓冲区。 在该行的末尾,创建的临时向量被删除,但它具有旧向量的内容,而旧向量具有新副本的内容,这正是我们需要的大小。

Go look at Scott Meyers Effective STL item 17.

Basically you can't directly reduce the storage size of a std::vector. resize() and reseve() 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:

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

If we have to copy the data over then we need to do the copy:

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

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.

逆夏时光 2024-08-02 15:36:55

惯用的解决方案是与新构建的向量进行交换。

vector<int>().swap(v);

编辑:我读错了问题。 上面的代码将清除向量。 OP希望保持元素不变,只需将capacity()缩小到size()

很难说 aJ 的代码是否能做到这一点。 我怀疑是否有便携式解决方案。 对于gcc,您必须查看它们的vector 的特定实现。

编辑:所以我查看了 libstdc++ 实现。 看来aJ的解决方案确实有效。

vector<int>(v).swap(v);

请参阅源代码,第 232 行。

The idiomatic solution is to swap with a newly constructed vector.

vector<int>().swap(v);

Edit: I misread the question. The code above will clear the vector. OP wants to keep the elements untouched, only shrink capacity() to size().

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 of vector.

edit: So I've peeked at libstdc++ implementation. It seems that aJ's solution will indeed work.

vector<int>(v).swap(v);

See the source, line 232.

嘿咻 2024-08-02 15:36:55

不,您无法在不进行复制的情况下减少向量的容量。 但是,您可以通过检查capacity()并在每次插入内容时调用reserve()来控制新分配的增长量。 std::vector 的默认行为是每次需要新容量时将其容量增加 2 倍。 您可以通过自己的神奇比率来增长它:

template <typename T>
void myPushBack(std::vector<T>& vec, const T& val) {
    if (vac.size() + 1 == vac.capacity()) {
        vac.reserve(vac.size() * my_magic_ratio);
    }

    vec.push_back(val);
}

如果您喜欢一些黑客技术,您可以随时传入自己的分配器并执行任何您需要执行的操作来回收未使用的容量。

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:

template <typename T>
void myPushBack(std::vector<T>& vec, const T& val) {
    if (vac.size() + 1 == vac.capacity()) {
        vac.reserve(vac.size() * my_magic_ratio);
    }

    vec.push_back(val);
}

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.

荭秂 2024-08-02 15:36:55

我并不是说 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 an Allocator doesn't include a reallocate() method. I don't think it would be impossible to do, but it might be tricky.

逆夏时光 2024-08-02 15:36:55

如果您担心向量的开销,那么也许您应该考虑使用另一种类型的数据结构。 您提到,一旦代码完成向量初始化,它就会成为只读进程。 我建议使用开放式数组,该数组将允许程序在编译时决定其容量。 或者也许链接列表更适合您的需求。
让我知道我是否完全误解了你的意思。

-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

白日梦 2024-08-02 15:36:55

老线程,我知道,但以防万一将来有人看到这个.. 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

撕心裂肺的伤痛 2024-08-02 15:36:55

我不是 C++ 专家,但似乎这个 解决方案有效(至少用 g++ 编译它可以):

std::vector<int>some_vector(20);//initial capacity 10
//first you gotta resize the vector;
some_vector.resize(10);
//then you can shrink to fit;
some_vector.shrink_to_fit();
//new capacity is 10;

I'm not an expert in C++,but it seems this solution works(atleast compiling it with g++ does):

std::vector<int>some_vector(20);//initial capacity 10
//first you gotta resize the vector;
some_vector.resize(10);
//then you can shrink to fit;
some_vector.shrink_to_fit();
//new capacity is 10;
时光无声 2024-08-02 15:36:55

这也有效:

在线尝试!

v = std::vector<T>(v); // if we need to keep same data
v = std::vector<T>(); // if we need to clear

它调用 && 重载= 运算符,它进行移动,swap() 使用相同的重载。

This also works:

Try it online!

v = std::vector<T>(v); // if we need to keep same data
v = std::vector<T>(); // if we need to clear

It calls && overload of = operator, which does moving, same overload is used by swap().

坠似风落 2024-08-02 15:36:55

获取 Scott Myers 所著的“Effective STL”一书。 它有一个完整的项目只是减少向量的容量。

Get the "Effective STL" book by Scott Myers. It has a complete item jus on reducing vector's capacity.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文