Home > OS >  linked list destructor with std::move c
linked list destructor with std::move c

Time:11-23

I'm learning data structures in C ;

I've written a destructor for a linked list as follows:

    ~List(){
        Node* temporary = new Node;
        Node* node = head;
        while(node != nullptr){
            temporary = node;
            node = node->next;
            delete temporary;
        }
    }

But then I realized that I can do:

        ~List(){
        Node* node = head;
        while(node != nullptr){
            node = std::move(node->next);
        }
    }

Avoiding creating a temporary object, I tried it and worked fine, but I don't know if it is okay, I didn't find a destructor like this in any other place.

CodePudding user response:

This code snippet

~List(){
    Node* temporary = new Node;
    Node* node = head;
    while(node != nullptr){
        temporary = node;
        node = node->next;
        delete temporary;
    }
}

produces a memory leak due to this unneeded memory allocation

    Node* temporary = new Node;

In this code snippet

    ~List(){
    Node* node = head;
    while(node != nullptr){
        node = std::move(node->next);
    }
}

neither memory is freed. Only the pointer node is reassigned until it will be equal to a null pointer. So there are again numerous memory leaks.

If you do not want to use an intermediate variable then the destructor can be written for example the following way

    #include <functional>

    //...

    ~List(){
        while ( head ) delete std::exchange( head, head->next );
    }
}

CodePudding user response:

std::move doesn't do anything by it's own, it only cast something to rvalue.

How the rvalue is used is determined by the function that accept it, and assignment of raw pointer does nothing different than copy in that case.

But for example, if you're using std::unique_ptr, the operator=(unique_ptr&&) would delete the original data after assignment*.


so if you're using something like

#include <memory>

struct Node{
   std::unique_ptr<Node> next;
   // possibly move List destructor here
   // i.e. destruct a Node would safely remove all sub-node non-recursively
};

struct List{
   std::unique_ptr<Node> head;
   // write destructor to prevent deep recursion
   ~List(){
      while(head) head = std::move(head->next); // current head is deleted after assignment
   }
};

then it would work


*btw, self-assignment is safe because it's actually effectively reset(r.release())

  • Related