C++ · Course navigation

C++ linked lists with unique ownership

Build a node chain with automatic destruction.

On this page
Before you start

Structs, pointers, move semantics, and smart pointers.

  • Build a node chain with automatic destruction.
  • Predict the sample output and explain the state changes.
  • Complete the practice task and check the boundary cases.

The concept

std::unique_ptr expresses exclusive ownership of a dynamically allocated object. Moving it transfers ownership and leaves the source empty.

Each node owns its successor. The raw current pointer only observes nodes during traversal; it neither deletes them nor outlives the owning chain.

Code example

C++
#include <iostream>
#include <memory>
#include <utility>
struct Node {
    int value;
    std::unique_ptr<Node> next;
    explicit Node(int v) : value(v) {}
};
int main() {
    auto head = std::make_unique<Node>(2);
    head->next = std::make_unique<Node>(3);
    auto first = std::make_unique<Node>(1);
    first->next = std::move(head);
    head = std::move(first);
    for (const Node* current = head.get(); current; current = current->next.get()) {
        std::cout << current->value << '\n';
    }
}
Output
1
2
3

Follow the code

Open the walkthrough to inspect the example one step at a time.

Show guided walkthrough
Guided walkthroughReady
1#include <iostream>
2#include <memory>
3#include <utility>
4struct Node {
5 int value;
6 std::unique_ptr<Node> next;
7 explicit Node(int v) : value(v) {}
8};
9int main() {
10 auto head = std::make_unique<Node>(2);
11 head->next = std::make_unique<Node>(3);
12 auto first = std::make_unique<Node>(1);
13 first->next = std::move(head);
14 head = std::move(first);
15 for (const Node* current = head.get(); current; current = current->next.get()) {
16 std::cout << current->value << '\n';
17 }
18}

Follow the example

Start to inspect the source, values, and output. These prepared steps explain the published sample; grouped loop steps describe multiple iterations.

View the complete dry-run table
Prepared trace of the published program. Some rows group repeated iterations.
Step / lineWhat happensState after stepOutput so far
Own the first allocation.head -> 2
—
Node 2 owns node 3.head -> 2 -> 3
—
Create a new leading node.first -> 1
—
Transfer the old chain into node 1.first -> 1 -> 2 -> 3; head = null
—
Make head own the whole chain.head -> 1 -> 2 -> 3; first = null
—
Observe and print each node in three iterations; owners clean up at scope exit.head -> 1 -> 2 -> 3; first = null
1
2
3

Behind the scenes

How C++ processes this code

The C++ compiler produces a native executable. Execution enters main, where objects and function calls perform the work.

Cost and common mistakes

O(1) prepend and O(n) traversal/destruction; O(n) node storage.

  • unique_ptr cannot be copied; ownership transfer requires a move.
  • Very long recursively owned chains can need iterative destruction to avoid deep destructor calls.

Try it yourself

What does first hold after head = std::move(first)?

Reveal answer and reasoning

It is empty. The chain is owned by head, so do not dereference first.

Further reading