C++ Singly Linked List with unique_ptr

A linked list is a chain of nodes, where every node keeps a value and a pointer to the next node. This version uses std::unique_ptr, so there is no delete and no memory leak.

Program

#include <iostream>
#include <memory>
#include <utility>

class LinkedList {
    struct Node {
        int value;
        std::unique_ptr<Node> next;
        explicit Node(int v) : value(v) {}
    };
public:
    void push_front(int v) {
        auto node = std::make_unique<Node>(v);
        node->next = std::move(head);
        head = std::move(node);
        count++;
    }

    void push_back(int v) {
        auto node = std::make_unique<Node>(v);
        if (!head) { head = std::move(node); count++; return; }
        Node* cur = head.get();
        while (cur->next) cur = cur->next.get();
        cur->next = std::move(node);
        count++;
    }

    bool contains(int v) const {
        for (const Node* cur = head.get(); cur; cur = cur->next.get())
            if (cur->value == v) return true;
        return false;
    }

    bool remove(int v) {
        std::unique_ptr<Node>* link = &head;
        while (*link) {
            if ((*link)->value == v) {
                *link = std::move((*link)->next);
                count--;
                return true;
            }
            link = &(*link)->next;
        }
        return false;
    }

    void reverse() {
        std::unique_ptr<Node> prev;
        while (head) {
            auto next = std::move(head->next);
            head->next = std::move(prev);
            prev = std::move(head);
            head = std::move(next);
        }
        head = std::move(prev);
    }

    void print() const {
        for (const Node* cur = head.get(); cur; cur = cur->next.get())
            std::cout << cur->value << (cur->next ? " -> " : "");
        std::cout << '\n';
    }

    std::size_t size() const { return count; }

private:
    std::unique_ptr<Node> head;
    std::size_t count = 0;
};

int main() {
    LinkedList list;
    list.push_back(2);
    list.push_back(3);
    list.push_front(1);
    list.print();

    std::cout << list.contains(3) << ' ' << list.contains(9) << ' ' << list.size() << '\n';
    list.remove(2);
    list.print();
    list.push_back(4);
    list.reverse();
    list.print();
}
Output

1 -> 2 -> 3
1 0 3
1 -> 3
4 -> 3 -> 1

Notes

  • The nodes are owned by their previous node. When the list is destroyed, the chain is deleted by the destructors. (Very long lists can overflow the stack in that recursive destruction, so a production list deletes the nodes in a loop.)
  • In real code use std::list or, much better, std::vector. Writing a list is a good way to learn pointers.

Related: Smart Pointers and C++ Pointers.


Learn more about the similar topics:
Tutorials
No Content Found.
Exercises & Assignments
No Content Found.
Interview Questions & Answers
No Content Found.