简体   繁体   中英

How to free the memory that is dynamically allocated by member functions of a Queue class which is implemented by Linked List?

I implemented a Queue class with linked list, which have the functions push and pop . The push function allocates some memory dynamically with the new operator each time is is called. My question is:

  1. How to free these memory allocated by the push function (assume pop isn't called)? Does the destructor I wrote work?
  2. If I were to create a Queue object dynamically by Queue* queue2 = new Queue(); , will calling delete queue2 free the memory allocated by push function (assume pop isn't called)?

Below is the code I wrote:

struct ListNode { 
    ListNode* next;
    int val;
    ListNode(int x) {
        val = x;
        this->next = nullptr;
    }
};

class Queue {
public:
    Queue() {
        head = nullptr;
        tail = nullptr;
    }
    
    // Destructor for freeing all dynamically allocated memory
    ~Queue(){
        if (head){
            ListNode* cur = head;
            ListNode* next;
            // iterate through the list and free all memory
            while (cur){
                next = cur->next;
                delete cur;
                cur = next;
            }
            head = nullptr;
        }
    }

    void push_front(int x) { // add node at then end of linked list
        // Need to dynamically allocate front bc want it to persist after leaving this block
        ListNode* front = new ListNode(x);
        if (!head) {
            head = front;
            tail = head;
        }
        else {
            tail->next = front;
            tail = tail->next;
        }
    }

    void pop_back() { // remove the first node of the linked list
        if (!head) {
            return;
        }
        ListNode* newHead = head->next;
        delete head; // free memory
        head = newHead;
    }

private:
    ListNode* head;
    ListNode* tail;
};


int main() {
    Queue queue = Queue();
    queue.push_front(1);
    queue.push_front(2);
}

Yes normally stuff allocated during the lifetime of the object are de-allocated in the destructor when the object is destroyed.

So answering your first question. Yes the destructor looks like it is doing the correct thing.


The unasked question is your code doing enough.
Here the answer is no. The problem is that the compiler generates a couple of methods automatically that do not work well with dynamic allocation, and you have to provide your manually implementation.

So your class is lacking a copy constructor and an copy assignment operator. This is known as The Rule of Three (Copy Constructor/Copy Assignment/Destructor).

{
    Queue   a;
    a.push_front(1);

    Queue   b(a);   // Problem is here.
                    // The default generated copy constructor
                    // creates a shallow copy of the object.
}
// the destruction of the objects b and a interact resulting in
// a double de-allocation of your ListNode.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM