C++ linked lists with unique ownership
Build a node chain with automatic destruction.
On this page
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
#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';
}
}1 2 3
Follow the code
Open the walkthrough to inspect the example one step at a time.
Show guided walkthrough
#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'; }}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 |
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.