Step 2 of 5
Unique means unique
"Unique" means exactly one owner at a time. If you could copy a unique_ptr, two of them would both try to delete the same object: a double free. So copying is deleted: it's a compile error. What you can do is move it, which hands ownership over and leaves the source empty (nullptr, C++'s type-safe version of C's NULL).
#include <iostream>
#include <memory>
#include <string>
#include <utility>
#include <vector>
struct Song {
std::string title;
int seconds;
};
int main() {
auto a = std::make_unique<Song>(Song{"Intro", 95});
// auto b = a; // error: use of deleted copy constructor
auto b = std::move(a); // ownership moves to b
std::cout << (a ? "a owns it" : "a is empty") << ", b has " << b->title << "\n";
std::vector<std::unique_ptr<Song>> playlist;
playlist.push_back(std::move(b));
playlist.push_back(std::make_unique<Song>(Song{"Outro", 130})); // a temporary moves in by itself
int total = 0;
for (const auto& s : playlist) total += s->seconds;
std::cout << playlist.size() << " songs, " << total << " seconds\n";
}
a is empty, b has Intro
2 songs, 225 seconds
How it works
std::move(a)says "I'm giving this away". After it,ais null, andif (a)is false.- A
vectorofunique_ptrowns all its objects. When the vector is destroyed, each element deletes its object. push_back(std::make_unique<...>(...))needs nostd::move: a temporary is already about to disappear, so it's moved automatically.- Loop with
const auto&. A plainautowould try to copy eachunique_ptr, which doesn't compile.
Taking ownership in a function
A parameter of type std::unique_ptr<T> (by value) means "this function takes ownership". The caller must write std::move(ptr), which makes the hand-over visible in the code. Inside the function, move it again to store it: items_.push_back(std::move(item));.
Your turn: complete Inventory::add, which takes ownership of an item and stores it in the vector. Then count() and total_value().