簡體   English   中英

刪除C ++中的動態指針數組

[英]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.

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