C++ Linked list using smart pointers

前端 未结 4 911
孤城傲影
孤城傲影 2020-12-29 14:01

I have only been using raw pointers for linked list with templates. For example, the member data, Node* head; and when I am inserting a node one of the

4条回答
  •  难免孤独
    2020-12-29 14:28

    There are basically two alternatives to set up a smart-pointer enhanced list:

    1. Using std::unique_ptr:

      template
      struct Node
      {
           Node* _prev;
           std::unique_ptr _next;
           T data;
      };
      
      std::unique_ptr > root; //inside list
      

      That would be my first choice. The unique-pointer _next takes care there are no memory leaks, whereas _prev is an observing pointer. Copy and such things, however, need to be defined and implemented by hand.

    2. Using shared_ptr:

      template
      struct Node
      {
           std::weak_ptr _prev;   //or as well Node*
           std::shared_ptr _next;
           T data;
      };
      
      std::shared_ptr > root; //inside list
      

      This is the safer alternative, but less performant than with a unique-pointer. Moreover, it is copyable by design.

    In both the idea is that one node owns the complete remaining list. Now when a node goes out of scope, there is no danger that the remaining list becomes a memory leak, as the nodes are iteratively destructed (starting from the last one).

    The _prev pointer is in both options only an observing pointer: it's task is not to keep the previous nodes alive, but only to provide a link to visit them. For that, a Node * is usually sufficient (--note: observing pointer means you never do memory related stuff like new, delete on the pointer).

    If you want more safety, you can also use a std::weak_ptr for that. this prevents from things like

    std::shared_ptr > n;
    {
        list li;
        //fill the list
        n = li.root->next->next; //let's say that works for this example
    }
    n->_prev; //dangling pointer, the previous list does not exists anymore 
    

    Using a weak_ptr, you can lock() it and in this way chack whether _prev is still valid.

提交回复
热议问题