[英]Debug assertion failed when deleting a vector of pointers
我有一個保存pointer
類的pointer
的vector
:
vector<Entity*> editorElements;
vector<Entity*> entities;
vector<DirectionalLight*> dirLights;
vector<PointLight*> pointLights;
vector<SpotLight*> spotLights;
這段代碼在我的Scene
類中。 Scene
的ctor和析構函數如下所示:
Scene()
{
editorElements = vector<Entity*>();
entities = vector<Entity*>();
dirLights = vector<DirectionalLight*>();
pointLights = vector<PointLight*>();
spotLights = vector<SpotLight*>();
}
~Scene()
{
delete[] &entities; // ERROR HERE
delete[] &dirLights;
delete[] &pointLights;
delete[] &spotLights;
delete[] &editorElements;
}
在析構函數中,我在ERROR HERE
標記了一行。 我先輸入哪個向量都沒有關系,但我總是會得到錯誤。 奇怪的是,直到最近(沒有碰到Scene
類或使用Scene
實例的任何其他類中的任何東西),它都運行良好,突然之間它引發了一個異常:
vector
s為空或有元素都沒有關系,它給出的誤差都相同。
我需要協助以解決此問題。
向量不是更新的指針,更不用說更新的數組了。 因此,您不應該刪除它們。 如果需要對向量中存儲的指針調用delete,則應遍歷向量,刪除每個元素。 但是最好改為存儲智能指針(例如std::unique_ptr<Entity>
。也就是說,如果您需要存儲所有指向動態分配對象的指針。
請注意,如果最終刪除了析構函數中的元素,則還需要注意3/5的規則 。
刪除表達式 delete [] x
的描述如下:
銷毀由new []表達式創建的數組
因此delete[] &entities
僅當&entities
是由new[]
-expression創建的數組時, delete[] &entities
才有意義。 對?
但是entities
是std::vector<Entity*>
,而不是Entity[]
。 您不是使用new[]
創建它的,因此不能使用delete[]
刪除它。
std::vector
不是數組的語法糖,它是模板類,而std::vector<Entity*> entities
不是數組,它是具有構造函數和析構函數的對象。 這也告訴我們,這句話
entities = vector<Entity*>();
沒有任何用處- entities
是一個對象,因此它已經是默認構造的。 您只是默認構造一個相同類型的匿名臨時文件,然后進行分配。
最后,在這里將原始指針存儲在向量中是可以的,因為向量不影響對象的生存期。 在大多數情況下,最好讓向量擁有對象,這樣您就不必擔心手動刪除它們,直接使用
vector<Entity>
或間接與
vector<unique_ptr<Entity>>
注意 一個好的原則是:你不應該使用new
, new[]
delete
或delete[]
在用戶代碼在所有 。
使用類對象來管理您的存儲,因為編譯器將為您調用其構造函數和析構函數。
如果需要自定義類,請編寫一個僅管理內存的類,以免與程序邏輯脫鈎。 否則,如果您確實需要該所有權模型,則只需使用標准庫工具,例如std::vector
, std::array
, std::unique_ptr
, std::shared_ptr
等等。
突然間它提出了一個例外
這是因為嘗試刪除不應該刪除的內容。 delete[]
語法用於刪除動態分配的數組 。 但是您為它提供了一個指向std::vector
實例的指針。 因此,編譯器將此地址當作刪除對象,就好像它是一個數組一樣,其中包括找出其大小,然后刪除整個段。 但是沒有合適的數字,因為它不是數組,所以在運行時,您最終試圖在沒有訪問權限的地方刪除某些內容,因此斷言失敗,因為這是訪問違反,也稱為段錯誤。
同樣, vector
是管理自己的內存的類。 如果要釋放保存在此容器中的實體(即,動態分配的各個元素本身),則應遍歷它們並刪除每個元素。 例如,方便地使用auto
和基於范圍的for循環,如下所示:
for (auto ptr : entities)
delete ptr;
但是,在大多數情況下,您最好節省這些內存管理開銷,並選擇std::unique_ptr
而不是原始指針:
#include <memory>
...
std::vector<std::unique_ptr<Entity>> entities;
這樣,您不必擔心釋放任何內存,因為一旦銷毀了std:: unique_ptr
,它就會被釋放,這是vector
銷毀的一部分。
此外,這是不必要的,可能不是您打算執行的操作:
entities = vector<Entity*>();
因為vector
對象本身已經在此行之前定義(因此存在),並且它所做的就是創建一個相同的新對象並將其分配給entities
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.