![](/img/trans.png)
[英]Proper way to delete and free up memory of a vector (prevent different memory related errors) in 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)。 然而,這是一個非綁定請求,您的實現可以隨意忽略它。
這里有兩件事:
例如:
{
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
有權保留原始存儲,以備日后使用。
如果您決定在1
和2
之間將更多內容推入其中,則可以節省時間,因為它可以重用舊內存。
在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.