[英]Deleting a dynamic array of pointers in C++
我有一個關於刪除C ++中的動態指針數組的問題。 假設我們有以下情況:
int n;
scanf("%d", &n);
Node **array1 = new Node*[n];
/* ... */
其中,Node是預先定義的特定結構。 假設在使用new運算符分配后,我們更改了array1的內容(但我們不刪除任何內容!)。 如果數組中可能存在重復的指針(不按線性順序對它們進行排序或插入到集合中),則刪除array1及其所有內容的正確方法是什么?
使用此分配:
Node **array1 = new Node*[n];
array1的內容是undefined 。 每個元素都是一個Node*
,並且由於內存尚未初始化,因此該值可以是任何值。
分配指針數組不會構造指向類的對象。
因此,無論將什么指針放入數組,它們指向的對象都需要在其他位置構造和銷毀。
因此,回答您的問題,刪除array1的正確方法是
delete[] array1;
但是,請注意, 這不會導致為每個Node*
調用析構函數- 在刪除數組之前,應處理放入數組中的所有內容。
編輯:我對原始問題感到困惑,它在數組中提到“更改值”, 就好像在您的示例中分配的數組中有一個有效值一樣。
但是...據我所知,您以后想要跟蹤要刪除的指針,也許您可以為此目的創建另一個數組,其中每個指針僅存在一次。 因此,您有了上面當前擁有的數組,其中包含指向可能會重復使用的節點的指針,無論您出於何種目的使用它。 然后,您將擁有另一個數組來明確管理刪除,每個指針僅出現一次。 在pNewNode = new Node()
之后pNewNode = new Node()
設置諸如nodeCleanupArray[i] = pNewNode
類的東西應該足夠容易,然后您可以在線性時間內遍歷該數組並delete
每個元素。 (這意味着您不必費心檢查array1中的元素,而是依靠nodeCleanupArray進行清理)
對於這種問題有很多解決方案,但是最明顯的選擇是將其更改為使用
std::vector< std::shared_ptr<Node> >
現在,您將擁有一個引用計數的指針,而無需編寫任何代碼,還有一個不需要知道其預定義大小的“數組”。
當然,您可以在Node
內實現引用計數的對象,也可以在自己的容器對象中實現相同的目的,但這似乎帶來了額外的麻煩,幾乎沒有好處。
嘗試標記和清除:)您正在嘗試實施托管環境。
這是一個例子:
struct Node
{
...
bool marked;
Node() : marked(false)
{}
};
現在刪除:
void do_delete(Node **data, size_t n)
{
size_t uniq = 0;
Node **temp = new Node*[n];
for (size_t i = 0; i < n; i++)
{
if (data[i] && !data[i]->marked)
{
data[i]->marked = true;
temp[uniq++] = data[i];
}
}
for (i = 0; i < uniq; ++i)
{
delete temp[i];
}
delete[] temp;
delete[] data;
}
我這樣做的方法是有一個引用計數器,並有一個Node :: deref方法,當引用計數為0時,它將刪除節點本身。當遍歷節點列表時,調用node-> deref實際上不會刪除該節點。對象,直到數組中的最后一個Node引用為止。
刪除array1及其所有內容的正確方法是什么
您顯示一個分配; new Node*[n]
。 此分配使程序有責任調用delete [] whatever_the_return_value_was
。 這僅與刪除該分配有關,而不與刪除“其所有內容”有關。 如果您的程序執行其他分配,則程序需要安排這些職責也要進行處理。
如果數組中可能存在重復的指針
那么delete
與當前分配不相關的指針值將是不確定的行為,因此您必須避免多次刪除同一指針值。 這不是一個單一正確方法的問題,而是編程實踐,設計等問題。
通常,C ++使用RAII來自動處理這些內容,而不是嘗試手動執行您想要的操作,因為手動執行確實很難正確。 在這里使用RAII的一種方法是擁有“擁有”節點的第二個對象。 然后,您的array1
將簡單地使用原始指針作為“非所有”指針。 然后,通過使擁有節點的對象超出范圍或以其他方式銷毀,可以刪除所有節點。
{
// object that handles the ownership of Node objects.
std::vector<std::unique_ptr<Node>> node_owner;
// your array1 object that may hold repeated pointer values.
std::vector<Node*> array1;
node_owner.emplace_back(new Node); // create new nodes
array1.push_back(node_owner.back().get()); // put nodes in the array
array1.push_back(node_owner.back().get()); // with possible duplicates
// array1 gets destroyed, but it's contents do not, so the repeated pointers don't matter
// node_owner gets destroyed and destroys all its Nodes. There are no duplicates to cause problems.
}
而且破壞確實發生在線性時間內。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.