2015-11-10 117 views
2

我有一個數據結構項目,我必須爲我的Uni類執行一個鏈接列表的堆棧;簡單的東西。我們在代碼方面有一些幫助,向我們展示了實現這種結構的正確方法。當我調用解構器時會造成內存泄漏嗎?

Stack類:

class Stack 
{ 
public: 
    Stack(void) 
    { 
     top = NULL;  // Initialises defualt top node pointer. 
    } 

    ~Stack(void) 
    { 
     while (NodePop() != NULL){} 
    } 

    void Push(int value) // Pushes a new node onto the stack. 
    { 
     Node* temp = new Node(value, top); // Creates a temporary node with a value and makes it 
              // point to the top node as the next node in the stack. 

     top = temp;       // Temporary node becomes the top node in the stack. 
    } 

    Node* NodePop(void) 
    { 
     /* Remove top node from the stack */ 
     Node* temp = top;      // Creates a temporary node to return, sets it to top node. 
     if (top != NULL) top = top->getNext(); // Points the stacks top node to the next node in the list. 
     return temp;       // Returns a pointer to the popped node still in the heap. 
    } 

    int Pop(void)  // Pops the top node off of the stack. Returns the nodes value. 
    { 
     Node* temp = NodePop();  
     int valueReturn = 0; 

     /* Sets the return value */ 
     if (temp != NULL) 
     { 
      valueReturn = temp->getVal(); // Set return value to the nodes value if there is a node left. 
     } 
     else 
     { 
      throw "Stack Empty";   // Throws exception if temp is NULL and stack is empty. 
     } 

     delete temp;   // Deletes the node entirely from the heap. 

     return valueReturn; 
    } 

private: 
    Node* top; 

}; 

Node類:

class Node 
{ 
public: 
    Node(int value, Node* nextptr = NULL, Node* prevptr = NULL, int currentpriority = 0) 
    { 
     /* Set initial variables for the node at creation */ 
     this->value = value; 
     this->next = nextptr; 
     this->prev = prevptr; 
     this->priority = currentpriority; 
    } 

    // bunch of getters and setters... 

private: 
    Node* next;  // Pointer to the next node. 
    Node* prev;  // Pointer to the previous node. 
    int priority; // Stores the node priority as a number 0-9. 
    int value;  // Stores the node value for printing. 

}; 

我們不能改變任何的等級結構的(太我的煩惱,NodePop()應該是私有的,但瓦特/ E)。

所以這裏NodePop()從本質上刪除頂部節點但不刪除它;它從鏈表中刪除對它的所有引用,但它從不從堆中刪除它,它只從Pop()中的堆中刪除。一切都很好(除了可以公開地調用NodePop()之外,我再也不允許將它私有)。但是當我調用析構函數時必須使用NodePop(),而不是Pop()。

那麼這是否意味着當NodePop()從析構函數運行時,節點永遠不會從堆中刪除?

如果是這樣,我將如何刪除它們,因爲它會運行nodePop()如果我有它在一段時間,做,或者如果語句條件,所以總會有一個節點留下未刪除?

+2

你給出的代碼有多少錯誤,什麼是內存泄漏或一千? –

+1

很不幸,在大學裏作爲C++的一個例子,這是一種恥辱。 Stroustrup在他的主題演講中提到了這個問題,講師將壞C作爲C++的入門介紹。 –

+0

我要對自己和你說慈善,並且說給他們寫一張便條,問他是否打算打電話給Pop,而不是NodePop,否則會泄漏。 – West

回答

0

事實上,節點不會被刪除,而且這段代碼會泄漏。您可以使用Valgrind等工具來驗證。

我的while更改爲類似while (Node *N = NodePop()) delete N;

僅供參考,這段代碼絕對不是地道的C++ 11。它基本上寫得很差,我希望能找到更多的錯誤。你的老師應該得到一個巴掌在手腕上呈現C++ 11這樣:-)

+0

感謝您的回答,我不知道您可以在while循環條件中創建變量,但我仍然是編程新手。 – RawrBawr

+0

不用擔心。我可以爲新的C++程序員推薦本書:http://www.stroustrup.com/programming.html - 由C++的發明人製作,它涵蓋了現代C++設計。 –

3

問題看代碼

~Stack(void) 
{ 
    while (NodePop() != NULL){} 
} 

Node* NodePop(void) 
{ 
    /* Remove top node from the stack */ 
    Node* temp = top;      // Creates a temporary node to return, sets it to top node. 
    if (top != NULL) top = top->getNext(); // Points the stacks top node to the next node in the list. 
    return temp;       // Returns a pointer to the popped node still in the heap. 
} 

你的析構函數調用NodePop(),直到函數返回NULL。我們來看看NodePop()的功能。代碼中的評論聲稱它Creates a temporary node to return這是不正確的。它創建一個指向Node(一個Node *)的指針並將該指針設置爲指向top所做的相同位置。如果top不爲空,則它將top設置爲指向頂部的下一個節點。它的回報爲temp,其中是指向最初的頂級節點

在任何時候,你都不會釋放與任何節點相關的內存,所以是的是有內存泄漏。

您可以通過刪除在析構函數中遇到的不爲NULL的每個Node *來修復泄漏。

+0

感謝您的回答。我的代碼中的評論很糟糕,在完成之前我仍然需要重新做一些評論,我明白這是一個指針。 – RawrBawr