根据C ++标准,std::vector<T>::pop_back()
是否曾被允许降低向量的容量?
我在问,因为我想要保证,以下代码将不抛出内存异常:
my_vec.pop_back();
if (...)
my_vec.push_back(...);
假设my_vec
是std::vector<int>
。
我猜有三种可能性:
是的,这可以根据C ++ 03和C ++ 11来实现。
不,C ++ 11禁止这样做(但C ++ 03没有)。
不,C ++ 03和C ++ 11都禁止这样做。
是的,我的问题与Does std::vector.pop_back() change vector's capacity?有关,但我的问题是关于标准保证的内容。
另请注意,Does std::vector.pop_back() change vector's capacity?中接受的答案主要是关于如何降低向量的容量,而不是关于何时保证不发生,并且没有提供任何证据声称关于pop_back()。
答案 0 :(得分:8)
根据http://en.cppreference.com/w/cpp/container/vector/pop_back
除了
back()
和end()
之外,没有任何迭代器或引用无效。
因此可能无法重新分配。该页面上没有C++11
标签,这意味着03年也是如此。我将挖掘部分参考并编辑它们以保证完整性。
修改:更好:来自C++03
:[lib.container.requirements](23.1),第10段:
没有
erase()
,pop_back()
或pop_front()
函数会抛出异常。
N3337(〜C++11
)中23.2.1 / 10的措辞相同。
答案 1 :(得分:5)
没有。缩小向量容量的唯一方法是交换技巧,如here所示。还有我提到的C++11
方式。
另外,正如ref所说:
移除向量中的最后一个元素,
有效地将容器尺寸缩小了一个。
换句话说,它会更改矢量的大小,不 容量。
查看迭代器有效性:
结束迭代器和任何迭代器,指针和引用
提到被删除的元素无效 参考其他的迭代器,指针和引用 未被删除的元素保证保留 指的是他们在电话会议之前提到的相同要素。
在C++11
中,您可以使用std::vector<>::shrink_to_fit()
来更改容量(有关更多信息,请参阅第1个链接)。 (tnx Psyduck)。有趣的评论低于答案,但这个问题与上述方法无关,所以如果有兴趣,请阅读评论。
请注意,即使这种方法也不能保证减少capacity
,因为ref说:
请求容器减小其容量以适应其大小。
请求是非绑定的,容器实现可以自由优化,否则&gt;并使向量的容量大于其大小。
这可能会导致重新分配,但对矢量大小没有影响,也无法改变其&gt;元素。
这个功能无法保证减少capacity
和pop_back
,而第二个参考不提及任何相关内容,这太奇怪了。
我看到它的方式,因为引用没有提及capacity
,这意味着它不需要,这意味着capacity
保持不变。
一个有趣的例子是:
#include <iostream>
#include <vector>
int main() {
const int N = 1000000;
std::vector<int> v1;
v1.reserve(N);
for (int i = 0; i < N; ++i) {
v1.push_back(i);
}
std::cout << v1.capacity() << " and size = " << v1.size() << std::endl;
for (int i = 0; i < N - 2; ++i) {
v1.pop_back();
}
std::cout << v1.capacity() << " and size = " << v1.size() << std::endl;
return 0;
}
输出:
1000000 and size = 1000000
1000000 and size = 2
capacity
显然没有减少。
[编辑]
另一个相关的question,也可以被标记为重复,有一些很好的答案。以下是一些有趣的内容:
1)
去看看Scott Meyers Effective STL第17项。(OP看起来有些参考) 基本上你不能直接减少std :: vector的存储大小。 “技巧”是指&gt;创建一个合适大小的新容器,复制数据并与当前容器交换。
2)
不,你不能在没有复制的情况下减少矢量的容量。
3)
我不是说GCC没有一些方法可以在没有副本的情况下做你想做的事,&gt;但实现(我认为)会很棘手,因为向量需要使用Allocator对象来分配和释放内存,而Allocator的接口不包含reallocate()方法。我不认为这是不可能的,但它可能会很棘手。
我建议阅读更多链接。
[EDIT.2]
此question也支持:
问:pop_back()
可以减少capacity
吗?
答:否。
如果您不能依赖适当的方法来减少容量(就您在标准中所读到的内容而言),您不能指望pop_back()
做类似的事情。
答案 2 :(得分:1)
评论并没有真正解决它。显然,如果禁止std :: vector使用除std :: allocator之外的任何东西,并且如果禁止使用其他方法扩展std :: allocator,则无法使用相同的基址进行大小调整,这使得无法减少容量,因为迭代器将失效。
关于重新分配的最近信息是关于Why is there no reallocation functionality in C++ allocators?的stackoverflow评论
&#34;在某些情况下,没有什么能阻止std :: vector执行此操作(例如,它使用标准分配器知道它)。允许标准库使用底层系统的知识。 - KeithB Jun 23&#39; 10 at 21:39&#34; (但没有提到参考文献)
已经提交了将realloc添加到std :: allocator的想法,但它们都被拒绝了:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1953.html
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2045.html
论文没有明确声明std :: allocator被禁止扩展std :: allocator,但是他们只是表明它并不需要。他们也没有明确声明禁止std :: vector使用对底层系统的API调用......所以也没有真正的信息。