我有一個關於在C++中刪除指針的動態數組的問題。假設我們有以下情況:在C++中刪除指針的動態數組
int n;
scanf("%d", &n);
Node **array1 = new Node*[n];
/* ... */
其中Node是事先定義的特定結構。假設在用new運算符分配之後,我們改變array1的內容(但是我們不會刪除任何東西!)。如果數組中存在重複指針的可能性(無需對它們進行排序或以線性時間插入集合),那麼刪除array1及其所有內容的正確方法是什麼?
我有一個關於在C++中刪除指針的動態數組的問題。假設我們有以下情況:在C++中刪除指針的動態數組
int n;
scanf("%d", &n);
Node **array1 = new Node*[n];
/* ... */
其中Node是事先定義的特定結構。假設在用new運算符分配之後,我們改變array1的內容(但是我們不會刪除任何東西!)。如果數組中存在重複指針的可能性(無需對它們進行排序或以線性時間插入集合),那麼刪除array1及其所有內容的正確方法是什麼?
使用這樣的分配:
Node **array1 = new Node*[n];
陣列1的內容是不確定。每個元素是Node*
,並且由於內存未初始化,該值可以是任何值。
分配一個指針數組而不是構造指向類的對象。
因此,無論您將哪些指針放入數組中,它們指向的對象都需要在別處構建和銷燬。
因此,要回答你的問題,刪除陣列1的正確方法是
delete[] array1;
但是,請注意這不會結果在析構函數被調用每個Node*
- 你應該處理任何你投入數組之前您刪除數組。
編輯: 我被原來的問題,其中提到的「改變價值」的陣列中,好像有數組中的有效值在你的榜樣分配混淆。
但是......現在我明白你想跟蹤稍後刪除的指針,也許你可以爲此目的創建另一個數組,每個指針只存在一次。因此,您有上面的數組,其中包含指向可能重複的節點的指針,無論您使用什麼目的。然後,您有另一個數組,用於管理刪除的表達目的,其中每個指針只出現一次。應該很容易在pNewNode = new Node()
之後設置nodeCleanupArray[i] = pNewNode
之類的東西,然後您可以在線性時間內通過該陣列和delete
每個元素。 (這意味着你不會打擾檢查array1中的元素,你會依賴nodeCleanupArray進行清理)
嘗試標記並掃描:)您正在嘗試實施託管環境。
下面是一個例子:
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將不會實際刪除對象,直到數組中的最後一個節點引用。
有這一類的問題,許多解決方案,但最明顯的選擇是去改變它使用
std::vector< std::shared_ptr<Node> >
現在你將有一個引用計數指針,而無需編寫任何代碼,「陣列「這並不需要知道它是預定義的大小。
您當然可以在Node
或您自己的容器對象中實現一個引用計數對象來執行相同的操作,但這看起來像是額外的麻煩,很少或沒有任何好處。
什麼是刪除
您展現一個分配陣列1及其所有內容的正確方法; new Node*[n]
。該分配賦予程序撥打delete [] whatever_the_return_value_was
的責任。這只是關於刪除一個分配而不是刪除「所有內容」。如果您的計劃執行其他分配,那麼計劃也需要安排這些責任進行處理。
如果有重複的指針數組中的可能性
那麼這將是不確定的行爲delete
不與任何當前分配相關聯的指針值,所以你要避免刪除相同的指針值不止一次。這不是存在單一正確方式的問題,而是編程實踐,設計等問題。
通常C++使用RAII來自動處理這些東西,而不是嘗試手動執行所需的操作,因爲它手工操作確實很難得到正確的結果。在這裏使用RAII的一種方法是擁有「擁有」節點的第二個對象。您的array1
然後將簡單地使用原始指針作爲「非擁有」指針。然後刪除所有節點將通過讓Node擁有的對象超出範圍或以其他方式被銷燬來完成。
{
// 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.
}
而且銷燬確實發生在線性時間。
數組中的指針本身是否分配在堆上? 如果是這樣,你可以給Node添加一個引用計數,或者可能有另一個只包含指向已分配節點的唯一指針的數組。 – Pete 2013-03-14 20:06:55
爲什麼這個標籤爲C++?如果你使用C++,只需使用矢量。 – none 2013-03-14 20:06:57
你的意思是改變'array1'本身的值,還是其中的指針?你沒有展示如何在代碼中創建'array1'的內容。 – 2013-03-14 20:07:14