Just Like auto_ptr, But Better
unique_ptrticks the right boxes. It implements a strict ownership semantics, it's slim and it's fast, with a memory footprint identical to that of a native pointer.
If you've used auto_ptr before you will notice that unique_ptrhas an almost identical interface:
#include <utility>
using namespace std;
unique_ptr<int> up1; //default construction
unique_ptr<int> up2(new int(9)); //initialize with pointer
*up2 = 23; //dereference
up2.reset(); //reset
assert (sizeof(auto_ptr<T>)==sizeof(unique_ptr<T>));
assert (sizeof(auto_ptr<T>)==sizeof(unique_ptr&lT>));
The main difference between auto_ptr and unique_ptr becomes visible in move operations. While auto_ptr sometimes disguises move operations as copy-operations, unique_ptr will not let you use copy semantics when you're actually moving an lvalue unique_ptr:
auto_ptr<int> ap1(new int);
auto_ptr<int> ap2=ap1; //OK but unsafe: move
//operation in disguise
unique_ptr<int> up1(new int);
unique_ptr<int> up2=up1; //compilation error: private
//copy ctor inaccessible
Instead, you must call move() when moving operation from an lvalue:
unique_ptr<int> up2 = std::move(up1);//OK
This makes unique_ptrsafe for usage with containers and algorithms.
Containers and Algorithms
If a container of unique_ptr objects moves elements internally instead of copying them, your code will work without problems. If, however, a container or an algorithm uses copy semantics for its value_typeyou will get a compilation error. Thus, you won't encounter a run time error due to a move operation being mistaken for a copy:
vector<unique_ptr<int> > vi;
v.push_back(unique_ptr<int>(new int(8)));
v.push_back(unique_ptr<int>(new int(4)));
v.push_back(unique_ptr<int>(new int(1)));
sort(v.begin(),v.end(),indirect_less()); //result {1,4,8}