[英]Can pop_back() ever reduce the capacity of a vector? (C++)
根據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都禁止這樣做。
是的,我的問題與std :: vector.pop_back()改變向量的容量有關嗎? ,但我的問題是關於標准保證的內容。
另請注意,在std :: vector.pop_back()中接受的答案會改變向量的容量嗎? 主要是關於如何減少向量的容量,而不是關於何時保證不發生,並且沒有提供關於pop_back()的聲明的證據。
根據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的措辭相同。
第萎縮向量的能力的唯一途徑是交換技巧,如圖所示這里 。 還有我提到的C++11
方式。
此外,正如裁判所說:
刪除向量中的最后一個元素,
有效地減少了一個容器的大小。
換句話說,它改變了矢量的大小而不是它的容量 。
看看迭代器的有效性 :
結束迭代器和任何迭代器,指針和引用
引用已刪除的元素無效。
指向其他的迭代器,指針和引用
保證保留未被刪除的元素
指的是他們在通話前提到的相同元素。
在C++11
您可以使用std::vector<>::shrink_to_fit()
來更改容量(有關更多信息,請參閱第1個鏈接)。 (tnx Psyduck)。 有趣的評論下面的答案,但這個問題不是關於上述方法,所以如果有興趣,請閱讀評論。
請注意,即使這種方法也不能保證降低capacity
,因為ref說:
請求容器減小其容量以適應其大小。
請求是非綁定的,並且容器實現可以自由地優化>並且使向量的容量大於其大小。
這可能會導致重新分配,但對矢量大小沒有影響,並且不能更改其>元素。
奇怪的是,這個函數不能保證減少capacity
和pop_back
,而第二個的ref 沒有提到任何相關的東西。
我看待它的方式,因為ref沒有提到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
顯然沒有降低。
[編輯]
另一個相關的問題 ,也可以被標記為重復,有一些很好的答案。 這里有一些有趣的:
1)
去看看Scott Meyers Effective STL第17項。(一些參考OP看起來)基本上你不能直接減少std :: vector的存儲大小。 “技巧”是>創建一個合適大小的新容器,復制數據並與當前容器交換。
2)
不,你不能在沒有復制的情況下減少矢量的容量。
3)
我並不是說GCC沒有一些方法可以在沒有副本的情況下做你想做的事情,>但實現起來會很棘手(我認為)因為向量需要使用Allocator對象來分配和釋放內存,分配器的接口不包含reallocate()方法。 我不認為這是不可能的,但它可能會很棘手。
我建議閱讀更多鏈接。
[EDIT.2]
這個問題也支持:
問: pop_back()
能否減少capacity
?
答: 沒有 。
如果你不能依賴適當的方法來減少容量(根據你在標准中讀到的內容),你不能指望pop_back()
做類似的事情。
評論並沒有真正解決它。 顯然,如果禁止std :: vector使用除std :: allocator之外的任何東西,並且如果禁止使用其他方法擴展std :: allocator,則無法使用相同的基址進行大小調整,這使得無法減少容量,因為迭代器將失效。
最近的信息我可以找到關於重新分配的一個stackoverflow注釋為什么在C ++分配器中沒有重新分配功能? 話
“在某些情況下,沒有什么能阻止std :: vector執行此操作(例如,它使用標准分配器知道它)。標准庫允許使用底層系統的知識。 - KeithB 2010年6月23日21:39 “(雖然沒有提到參考文獻)
已經提交了將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調用......因此也沒有真正的信息。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.