C++ linked lists with unique ownership
Build a node chain with automatic destruction.
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
Explanation
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.
Explore the dry run
Guided walkthroughReady
1
#include <iostream>2
#include <memory>3
#include <utility>4
struct Node {5
int value;6
std::unique_ptr<Node> next;7
explicit Node(int v) : value(v) {}8
};9
int 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
| Step / line | What happens | State after step | Output 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 |
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.