Move semantics

C++11 introduced the concept of move semantics, which is kind of an optimized way to copy data. When an object is moved, the contents of the object is taken over by the destination, this is different from copying the data because no valuable data is left in the old object. Move operations are therefore faster because no copying is involved, we simply move the contents of one object into another.

This changed very much how solid objects are handled in C++. Before, returning an object from a function was in many cases too expensive since all the data in the returned object would be copied to the new object. This led to the coding pattern of returning pointers to data, or to pass the return value as a parameter to a function.

However, using move semantics, we can instead return solid objects from functions without any performance penalties

The downside is that we now need to consider implementing the move constructor and move assignment operator when creating a class, in addition to the copy constructor, copy assignment operator and destructor.

Move constructor and Move assignment operator

These operators take the following form

In the move constructor and move assignment operator, you are free to steal whatever data there is in the other object. The double ample sand (&&) means an r-value reference, and this is a reference to an object which is about to die, meaning that it is going to go out of scope and we can take whatever is in it. So for example, if the class in the previous example contained a pointer to a buffer, we could take ownership of this in the move constructor, like this

However this contains a lot of duplicated code, which is very bad. A good way around this is to let the move constructor call the move assignment operator

Which is a lot shorter!

The standard containers are with C++11 also move-enabled, i.e. there are move constructor and move assignment operators defined in each of them. For example when returning a vector from a function, the created vector is moved to the outer scope and the internal pointer is moved from the dying object to the new object.

As a side note, there is sometimes a point in making a class movable by defining the move assignment operator and move constructor but prohibiting copying the class by deleting the copy constructor and copy assignment operator. An example of a class where this is done is the std::unique_ptr, which if it would allow copying would make the pointer not unique which is contrary to the whole point of the class!

Recommendations

  • To prevent memory leaks, always free any resource which may be present in the current object before taking over the other objects data in the move constructor and move assignment operators.
  • Always check for self-assignment in the move assignment operator.
  • Make use of the move assignment operator in the move constructor to remove redundancy.
  • If you define a move constructor, then also add a move assignment operator (see the C++ core guidelines).
Facebookgoogle_pluslinkedinmail

Why should I use nullptr instead of NULL?

C++11 introduced the new keyword nullptr which is used to indicate a null pointer. This is different from the old NULL which was just a zero (usually an integer).

To understand why nullptr was introduced, consider the following example:

the developer probably intended to call the overload of f taking a pointer. However, since NULL is not a pointer but an integer, the overload of f taking an integer is going to be called.

If the developer instead wrote:

then the code would be much more clear in its intent.

Facebookgoogle_pluslinkedinmail

Shared pointer – std::shared_ptr

With C++11 came a new smart pointer class, std::shared_ptr.

Copyable

The shared pointer is allocated on the stack, exactly like the std::unique_ptr, but unlike the unique pointer is it possible to copy the shared pointer. Just like the unique_ptr will the contents which the smart pointer manages be deleted once the smart pointer goes out of scope. The difference is that the resource will only be deleted when all copies of the shared_ptr have gone out of scope. That is to say that as long as there is at least one handle to the shared memory then the resource will not be cleared.

Performance

The behavior of the std::shared_ptr is in practice implemented through reference counting, creating a new copy of a std::shared_ptr increases a counter of the number of live instances and as each copy goes out of scope this counter is decreased one step. When the counter finally reaches zero then the memory is released. This reference counting means that there is a slight overhead with using a shared_ptr compared to using the unique_ptr which doesn’t have this overhead.

std::weak_ptr

There is also one danger with the shared_ptr, it is possible to create dependency chains where two objects references each other through a shared_ptr and none of the two objects will ever be cleared because there is always one reference to each (by the other object). This “bug” can be resolve by using the third smart pointer introduced in C++11, the std::weak_ptr. A weak pointer is like a copy of a shared_ptr but creating it does not increase the reference count. Therefore, when the object is only reference by weak pointers then the memory will be deleted. The weak pointer can be converted into a std::shared_ptr (which you should do before trying to use it) and if the memory referenced to by the weak_ptr has already been released then you will get an empty shared_ptr back.

Creating – std::make_shared

You create instances of shared_ptr using the helper method std::make_shared. You can of course fill in the contents of the shared pointer yourself but the make_shared method is more efficient (one memory operation less than if you do it yourself) and has the advantage that if the constructor of the object throws an exception then the std::make_shared will make sure that no memory leak occurs.

 

Facebookgoogle_pluslinkedinmail

std::array : safe C arrays

The std::array was a new container introduced in C++11. A std::array works in the same way as a plain old C array (like int values[5]) but has the advantage that it will not decay into a plain pointer.

Unlike the vector can an array not be resized once it has been created.

Creating

std::array is always allocated on the stack. It it allocated using uniform initialization:

Iterating

You can iterate through each of the values in the array using range-based for:

or using std::for_each and a lambda

Facebookgoogle_pluslinkedinmail

Unique Pointer – std::unique_ptr

With C++11 came a new smart pointer class, std::unique_ptr.

This is a great class to use when you need to allocate an object which must have a life time longer than the current local scope. In old C++, this would be done by creating the object on the free store using new. It would then be up to you as a programmer to decide when the object is no longer necessary and then call delete on the pointer. The new unique pointer frees you from remembering when to call delete. The key feature of the unique pointer is that is just that, unique. There can be one and only one pointer to the managed object and no copies can ever be made. If you need a pointer which can be shared between many classes then you should instead go for shared_ptr.

The unique pointer is stored on the local scope and when it goes out of scope then the contents of the pointer will be deleted.

Non copyable

The key feature with the unique pointer is that it is unique, this means that no copies of the unique_ptr can ever be made. This has as a side effect that an object which owns a unique_ptr as a member variable can itself not be copied. If you think about it, then this is actually the same behavior as in old C++ when you instead would create a pointer using new and store the pointer as a member variable in a class. That pointer caused problems when you tried to make copies of the owning object, because who should own (and then also delete) the pointer after the copy was made? The original object or the copy? In practice this made the object not copyable unless you explicitly wrote an copy constructor and copy assignment operator. The difference is that in the old way would the program still compile and run. Modern C++ stops you from doing this, it tries to stop you from shooting yourself in the foot!

 Movable

The unique pointer is on the other hand movable, this means that it is possible to create a unique_ptr inside a function and then return the created pointer. It also means that objects owning a unique pointer will themselves also be movable without you having to do anything.

Make

C++11 introduced the std::make_shared function which made it possible to create a shared_ptr safely and easily. However, the make_unique function wasn’t added until C++14 simply because of an oversight in the review. If your compiler supports C++14 then you can create the unique pointer like this

where the parameters to the constructor of the class are passed in the parenthesis

Facebookgoogle_pluslinkedinmail

Deleted functions

In C++11 is it possible to remove a function from a class by using the delete specifier. If you try to use a deleted function will give a compiler error.

As an example, the following class is made non-movable by making it impossible to call the move operator and move constructor:

We can also stop anyone from creating instances of a class on the free store (heap)  by deleting the new operator:

Or more compact by using a template

To stop users from calling a method with specific parameters, delete the functions with the not allowed parameters:

 

Facebookgoogle_pluslinkedinmail

The auto keyword

The auto keyword was changed in C++11 from being completely unnecessary to being a highly useful keyword.

Auto variable type (C++11)

The auto keyword tells the compiler to set the type of a variable to the type of the value that we assign to the variable. For example:

If you don’t assign a value to the variable, then the compiler will be lost and will refuse to compile since it cannot figure out the type to set;

auto can be really useful when some of the standard library operations where the type names can be really complex:

when creating a local lambda expression, then auto is a must:

Auto return type (C++14)

Beginning in C++14 can the return type of a function be auto:

Auto as lambda parameter (C++14)

From C++14 we can also use the auto keyword for the type of the parameters when writing a lambda expression. The lambda itself will then be a generic lambda, i.e. it will be compiled as a template:

will be compiled as:

 

Facebookgoogle_pluslinkedinmail

Range-based for

With C++11 we got a new way of writing for-loops to iterate over all elements in a range. The new range-based for loop is much clearer than the old way using iterators. It is intended to be used when you only look at the elements in a container, you are not supposed to change the container itself since this could cause problems in the loop.

An example of how the new range-based for works, using a vector as an example:

When the vector contains an object then it’s a good idea to get a reference to the object to avoid copying the entire object in each round in the loop.

If the contents of the vector shouldn’t be changed then we can show this by getting a const reference:

We can use the auto keyword to avoid explicitly giving the type:

 

Facebookgoogle_pluslinkedinmail

Override

The override specifier was added in C++11 and is used to show that a method is overriding another method in a base class. When you use this specifier the compiler will help you to make sure that you are using the same signature in the new method as in the base class method.

Examples:

 

Why should we use this?

 

  • Because this makes your code more clear, adding override to your function makes it clear to anyone reading the code later that this is an override of a base class function.
  • It is very easy to accidentally create a new virtual function in a derived class when you intended to override a function in a base class by making an error in the signature of the function (like forgetting a const).
Facebookgoogle_pluslinkedinmail

The constexpr keyword

 

The keyword constexpr is used to show that a constant is resolved at compile time. This is a new keyword introduced with C++11.

Both constexpr and const are used to show that something is constant and the difference is that a constexpr value must be resolved at compile time  whereas a const can be resolved at run time or at compile time.

In most cases there is no real difference between a compile time or a run time constant but in some cases must the constant be defined at compile time. One example is creating fixed size arrays where the size must be a constant defined at compile time:

constexpr can also be used for function calls

However, a constexpr function must only consist of a single return statement, only call constexpr functions and only access constexpr global/member variables.

The purpose of constexpr is to replace macros and hard coded literal values without sacrificing performance or type safety.

Facebookgoogle_pluslinkedinmail