簡體   English   中英

pop_back()能否減少向量的容量? (C ++)

[英]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_vecstd::vector<int>

我想有三種可能性:

  1. 是的,這可以根據C ++ 03和C ++ 11來實現。

  2. 不,C ++ 11禁止這樣做(但C ++ 03沒有)。

  3. 不,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說:

請求容器減小其容量以適應其大小。

請求是非綁定的,並且容器實現可以自由地優化>並且使向量的容量大於其大小。

這可能會導致重新分配,但對矢量大小沒有影響,並且不能更改其>元素。

奇怪的是,這個函數不能保證減少capacitypop_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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM