簡體   English   中英

C++ 刪除向量、對象、空閑內存

[英]C++ delete vector, objects, free memory

我對在 C++ 中刪除東西感到非常困惑。 如果我聲明了一個對象數組並且我使用了clear()成員函數。 我能確定內存被釋放了嗎?

例如 :

tempObject obj1;
tempObject obj2;
vector<tempObject> tempVector;

tempVector.pushback(obj1);
tempVector.pushback(obj2);

我可以安全地調用 clear 來釋放所有內存嗎? 還是需要遍歷一遍才能刪除?

tempVector.clear();

如果把這個場景換成一個對象的指針,答案會不會和上面一樣?

vector<tempObject> *tempVector;
//push objects....
tempVector->clear();

您可以調用 clear,這將銷毀所有對象,但不會釋放內存。 循環遍歷各個元素也無濟於事(您甚至建議對對象采取什么行動?)您可以做的是:

vector<tempObject>().swap(tempVector);

這將創建一個沒有分配內存的空向量,並將其與 tempVector 交換,從而有效地釋放內存。

C++11 也有函數shrink_to_fit ,你可以在調用 clear() 之后調用它,理論上它會縮小容量以適應大小(現在是 0)。 然而,這是一個非綁定請求,您的實現可以隨意忽略它。

這里有兩件事:

  1. 對象生命周期
  2. 儲存期限

例如:

{
    vector<MyObject> v;
    // do some stuff, push some objects onto v
    v.clear(); // 1
    // maybe do some more stuff
} // 2

1 ,您清除v :這會破壞它存儲的所有對象。 每個都調用它的析構函數,如果你寫了一個,那么MyObject擁有的任何東西現在都被釋放了。 但是,vector v有權保留原始存儲,以備日后使用。

如果您決定在12之間將更多內容推入其中,則可以節省時間,因為它可以重用舊內存。

2 ,向量v超出范圍:從1推入它的任何對象都將被銷毀(就像您再次明確調用 clear 一樣),但現在底層存儲也被釋放( v不會出現在再使用它)。


如果我更改示例,使v成為指向動態分配向量的指針,則您需要顯式刪除它,因為在2處超出范圍的指針不會為您執行此操作。 在這種情況下最好使用std::unique_ptr類的東西,但如果你不這樣做並且v被泄露,它分配的存儲也會被泄露。 如上所述,您需要確保v被刪除,並且調用clear是不夠的。

vector::clear()不會釋放 vector 分配的內存來存儲對象; 它為它持有的對象調用析構函數。

例如,如果vector使用一個數組作為backing store,當前包含10個元素,那么調用clear()會調用數組中每個對象的析構函數,但是backing數組不會被deallocated ,所以還是有sizeof(T) * 10個字節分配給向量(至少)。 size()將為 0,但size()返回向量中的元素數,不一定是后備存儲的大小。

至於您的第二個問題,您使用new分配的任何內容都必須使用delete解除分配。 出於這個原因,您通常不會維護指向向量的指針。 很少有(如果有的話)這樣做的充分理由,並且當向量離開作用域時,您會阻止它被清理。 然而,不管它是如何分配的,調用clear()仍然會以相同的方式運行。

如果我使用clear()成員函數。 我能確定內存被釋放了嗎?

不, clear()成員函數會銷毀向量中包含的每個對象,但它使向量的容量保持不變。 它影響向量的大小,但不影響容量。

如果要更改向量的容量,可以使用clear-and-minimize idiom ,即創建一個(臨時)空向量,然后交換兩個向量。


您可以輕松了解每種方法如何影響容量。 考慮以下函數模板,它在傳遞的向量上調用clear()成員函數:

template<typename T>
auto clear(std::vector<T>& vec) {
   vec.clear();
   return vec.capacity();
}

現在,考慮將傳遞的向量與空向量交換的函數模板empty_swap()

template<typename T>
auto empty_swap(std::vector<T>& vec) {
   std::vector<T>().swap(vec);
   return vec.capacity();
}

兩個函數模板都返回返回時刻向量的容量,然后:

std::vector<double> v(1000), u(1000);
std::cout << clear(v) << '\n';
std::cout << empty_swap(u) << '\n';

輸出:

1000
0

移動語義允許通過簡單地從空右值應用 賦值 (=) 運算符來提供一種直接的方法來釋放內存:

std::vector<uint32_t> vec(100, 0);
std::cout << vec.capacity(); // 100

vec = vector<uint32_t>();    // Same as "vector<uint32_t>().swap(vec)";    
std::cout << vec.capacity(); // 0

它與其他答案中描述的基於“swap()”的方法一樣有效(實際上,兩者在概念上都在做同樣的事情)。 然而,在可讀性方面,作業版本在表達程序員意圖方面做得更好,同時更簡潔。

您可以通過這種方式釋放 vector 使用的內存:

//Removes all elements in vector
v.clear()

//Frees the memory which is not used by the vector
v.shrink_to_fit();

如果您需要一遍又一遍地使用向量,並且您當前的代碼在循環中或每次函數調用中重復聲明它,則很可能會耗盡內存。 我建議你在外面聲明它,在你的函數中將它們作為指針傳遞並使用:

my_arr.resize()

這樣,您可以繼續為向量使用相同的內存序列,而不是每次都請求新序列。 希望這有幫助。 注意:將其調整為不同的大小可能會添加隨機值。 如果需要,傳遞一個整數(例如 0)來初始化它們。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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