使std::vector 容量>=N 且大小=0 的最佳方法?

the best way to make a std::vector capacity>=N and size=0?

给定一个 std::vector,其大小和容量可以是任意的,将其大小更改为 0 并将容量更改为至少 N(给定数字)的最佳做法是什么?

我的直接想法是:

void f(vector<int> &t, int N)
{
    t.clear();
    t.reserve(N);
}

但我注意到

A reallocation is not guaranteed to happen, and the vector capacity is not guaranteed to change(when std::vector::clear is called).

所以我想知道当原始容量大于给定的 N 时如何避免重新分配?

what's the best practice to change its size to 0 and capacity to N(a given number)? My direct idea is: ...

你的直接想法是正确的,也是最简单的选择。尽管有点迂腐,reserve 将容量更改为 更大或 等于给定的数字;不保证相等(但我测试过的所有实现确实会在以前的容量较小的情况下分配给定的数量)。

So I'm wondering how to avoid reallocating when the origin capacity is larger than the given N?

通过使用已选择在调用 clear 时不释放内存的标准库实现(即任何符合标准的实现,如答案 here 所示)。


另一种保证方法(尽管cplusplus.com上的措辞薄弱,但似乎没有必要,因为上面应该得到保证)不重新分配(在N > t.capacity()的情况下):由于该向量包含简单的整数,并且您似乎知道将有多少元素(正如您所知道的那样),您可以简单地调用 t.resize(N) (以删除额外的元素以防大小更大)而不清除向量,然后继续覆盖现有元素,而不是推送新元素。

当然,这意味着您将无法观察到被覆盖的元素数量,因此这种方法并不适用于所有用例。如果您只是想用一个简单的循环填充向量,那很好。

如果新大小可能大于旧大小,您可能希望在调整大小之前保留,并且您不想过度分配。这是因为大多数实现都分配了精确的保留量(正如我提到的),但在调整大小时使用了乘法策略(据我所知,这些行为都没有得到保证,但我使用的实现与此行为一致)。

注意:此答案回答了以下问题:

the best way to make a std::vector capacity=N and size=0?

what's the best practice to change its size to 0 and capacity to N(a given number)?

在发布此答案后添加了对“>= N”的更改以及避免重新分配的要求。


标准不提供任何保证的方法来实现这一点。但你最好的机会是:

 t.clear();
 t.shrink_to_fit();
 t.reserve(N);

建议第二次调用以减少容量以匹配当前大小(届时为0)。

另一个可能有效也可能无效的替代方案是:

t.swap( std::vector<int>{} );
t.reserve(N);

最好的方法可能是您当前的代码。

不幸的是,该标准允许实现具有容量只能增长的容器。在这种情况下,您的代码将仅保证容量 至少 N。如果初始容量小于 N,则会发生重新分配,如果容量大于 N,则不会发生任何事情。这点数由标准保证,因为 C++17 的草案 4659 在 [vector.capacity](强调我的)处说:

void reserve(size_type n);
...
3 Effects: A directive that informs a vector of a planned change in size, so that it can manage the storage allocation accordingly. After reserve(), capacity() is greater or equal to the argument of reserve if reallocation happens; and equal to the previous value of capacity() otherwise. Reallocation happens at this point if and only if the current capacity is less than the argument of reserve().

void shrink_to_fit();
...
8 Effects: 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 ] It does not increase capacity(), but may reduce capacity() by causing reallocation.

您无法保证容量恰好为 N。相反,您的代码保证如果初始容量大于 N in 将保持不变并且不会发生重新分配。

编辑:此行为至少自 C++11(草案 n3337)以来是稳定的