Getting started
Literals
Basic type keywords
Operator precedence
Floating point arithmetic
Bit operators
Bit manipulation
Bit fields
Arrays
Flow control
const keyword
Loops
mutable keyword
friend keyword
keywords
Variable declaration keywords
auto keyword
Pointers
Type keywords (class, enum, struct, union)
Classes / structs
std::string
Enumeration
std::atomic<T>
std::vector
std::array
std::pair
std::map
std::unordered_map
std::set and std::multiset
std::any
std::variant
std::optional
std::integer_sequence
std::function
std::forward_list
std::iomanip
Iterators
Basic I/O
File I/O
Streams
Stream manipulators
Metaprogramming
Returning multiple values from a function
References
Polymorphism
Value and reference semantics
Function call by value vs. by reference
Copying vs assignment
Pointers to class / struct members
The this pointer
Smart pointers
Syntax
Unique ownership (std::unique_ptr)
Sharing ownership std::shared_ptr
Sharing with temporary ownership std::weak_ptr
Using custom deleters to create a wrapper to a C interface
Casting std::shared_ptr pointers
Writing a smart pointer value_ptr
Getting a shared_ptr referring to this
Unique ownership without move semantics std::auto_ptr
Unions
Templates
Namespaces
Function overloading
Operator overloading
Lambdas
Threading
Value categories
Preprocessor
SFINAE
Rule of three, five and zero
RAII
Exceptions
Implementation-defined behavior
Special member functions
Random numbers
Sorting
Regular expressions
Perfect forwarding
Virtual member functions
Undefined behavior
Overload resolution
Move semantics
Pimpl idiom
Copy elision
Fold expressions
Unnamed types
Singleton
ISO C++ Standard
User-defined literals
Type erasure
Memory management
Explicit type conversions
RTTI
Standard library algorithms
Expression templates
Scopes
Atomic types
static assert
constexpr
Date and time with std::chrono
Trailing return type
Function template overloading
Common compile linker errors
Design patterns
Optimizations
Compiling and building
Type traits
One definition rule
Unspecified behavio
Argument dependent name lookup
Attributes
Internationalization
Profiling
Return type covariance
Non-static member functions
Recursion
Callable objects
Constant class member functions
C++ vs. C++ 11 vs C++ 17
Inline functions
Client server examples
Header files
Const correctness
Refactoring techniques
Parameter packs
Iteration
type deduction
C++ 11 memory model
Build systems
Concurrency with OpenMP
Type inference
Resource management
Storage class specifiers
Alignment
Inline variables
Linkage specifications
Curiusly recurring template pattern
Using declaration
Typedef and type aliases
Layout of object types
C incompatibilities
Optimization
Semaphore
Thread synchronization
Debugging
Futures and promises
More undefined behaviors
Mutexes
Recursive mutex
Unit testing
decltype
Digit separators
C++ Containers
Arithmetic meta-programming
Contributors

Unique ownership (std::unique_ptr)

suggest change

A std::unique_ptr is a class template that manages the lifetime of a dynamically stored object. Unlike for std::shared_ptr, the dynamic object is owned by only one instance of a std::unique_ptr at any time,

// Creates a dynamic int with value of 20 owned by a unique pointer 
std::unique_ptr<int> ptr = std::make_unique<int>(20);

(Note: std::unique_ptr is available since C++11 and std::make_unique since C++14.)

Only the variable ptr holds a pointer to a dynamically allocated int. When a unique pointer that owns an object goes out of scope, the owned object is deleted, i.e. its destructor is called if the object is of class type, and the memory for that object is released.

To use std::unique_ptr and std::make_unique with array-types, use their array specializations:

// Creates a unique_ptr to an int with value 59
std::unique_ptr<int> ptr = std::make_unique<int>(59);

// Creates a unique_ptr to an array of 15 ints
std::unique_ptr<int[]> ptr = std::make_unique<int[]>(15);

You can access the std::unique_ptr just like a raw pointer, because it overloads those operators.

You can transfer ownership of the contents of a smart pointer to another pointer by using std::move, which will cause the original smart pointer to point to nullptr.

// 1. std::unique_ptr
std::unique_ptr<int> ptr = std::make_unique<int>();

// Change value to 1
*ptr = 1;

// 2. std::unique_ptr (by moving 'ptr' to 'ptr2', 'ptr' doesn't own the object anymore)
std::unique_ptr<int> ptr2 = std::move(ptr);

int a = *ptr2; // 'a' is 1
int b = *ptr;  // undefined behavior! 'ptr' is 'nullptr'
               // (because of the move command above)

Passing unique_ptr to functions as parameter:

void foo(std::unique_ptr<int> ptr)
{
    // Your code goes here
}

std::unique_ptr<int> ptr = std::make_unique<int>(59);
foo(std::move(ptr))

Returning unique_ptr from functions. This is the preferred C++11 way of writing factory functions, as it clearly conveys the ownership semantics of the return: the caller owns the resulting unique_ptr and is responsible for it.

std::unique_ptr<int> foo()
{
    std::unique_ptr<int> ptr = std::make_unique<int>(59);
    return ptr;
}

std::unique_ptr<int> ptr = foo();

Compare this to:

int* foo_cpp03();

int* p = foo_cpp03(); // do I own p? do I have to delete it at some point?
                      // it's not readily apparent what the answer is.

The class template make_unique is provided since C++14. It’s easy to add it manually to C++11 code:

template<typename T, typename... Args>
typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
make_unique(Args&&... args)
{ return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); }

// Use make_unique for arrays
template<typename T>
typename std::enable_if<std::is_array<T>::value, std::unique_ptr<T>>::type
make_unique(size_t n)
{ return std::unique_ptr<T>(new typename std::remove_extent<T>::type[n]()); }

Unlike the dumb smart pointer (std::auto_ptr), unique_ptr can also be instantiated with vector allocation (not std::vector). Earlier examples were for scalar allocations. For example to have a dynamically allocated integer array for 10 elements, you would specify int[] as the template type (and not just int):

std::unique_ptr<int[]> arr_ptr = std::make_unique<int[]>(10);

Which can be simplified with:

auto arr_ptr = std::make_unique<int[]>(10);

Now, you use arr_ptr as if it is an array:

arr_ptr[2] =  10; // Modify third element

You need not to worry about de-allocation. This template specialized version calls constructors and destructors appropriately. Using vectored version of unique_ptr or a vector itself - is a personal choice.

In versions prior to C++11, std::auto_ptr was available. Unlike unique_ptr it is allowed to copy auto_ptrs, upon which the source ptr will lose the ownership of the contained pointer and the target receives it.

Feedback about page:

Feedback:
Optional: your email if you want me to get back to you:



Table Of Contents
12 Loops
52 Unions
61 SFINAE
63 RAII
85 RTTI
88 Scopes
140 Mutexes