Transition to C++11 : The most important features

Introduction – Overview : C++11 brings many features. In this article I will try to look at features that I think as the most important ones. Please note that, this writing doesn`t intend to teach C++11 features , but it is more about providing a list of features. Initially I would like to share links that give an overview of the C++11 features :

– Wikipedia page :
http://en.wikipedia.org/wiki/C%2B%2B11

– C++11 cheat sheet, a really nice pdf :
http://isocpp.org/blog/2012/12/c11-a-cheat-sheet-alex-sinyakov

– Bjarne Strostroup`s FAQ about C++11 :
http://www.stroustrup.com/C++11FAQ.html

Introduction – Compiler support : Also regarding compiler support for C++11 , GCC 4.8 and later completely supports it. However in Microsoft side, even though we can say Visual Studio 2015 Preview edition is “almost” C++11 complete ( No support for attributes and SFINAE, “partial” support for constexpr & user defined literals ) :

– A complete comparison table :
http://en.cppreference.com/w/cpp/compiler_support

– GNU GCC/G++ features table :
https://gcc.gnu.org/projects/cxx0x.html

– Microsoft compilers` features table :
http://blogs.msdn.com/b/vcblog/archive/2014/11/17/c-11-14-17-features-in-vs-2015-preview.aspx

In my experiences, GCC starts to become stable with 4.8 as I had interesting issues with GCC 4.7. For example STL containers can reallocate data. And during that reallocation , if you want your move constructor`s being used , it has to be noexcept(true) since STL containers will use std::move_if_noexcept. However as this is not enough in GCC 4.7 , you will also need to use the exception specifier noexcept(true) for your destructor as well : http://stackoverflow.com/questions/15721544/destructors-and-noexcept

In Microsoft C++ side if you are using Visual Studio 2012, you have to be careful about variadic template usage. For example, as I tried to integrate GoogleTest libraries to a project, I had an issue with compilation due to variadic template usage in Google Test libraries. In VS2012 , variadic templates are implemented such a way called “Faux variadics” which implements variadic templates with macros. And there is also preprocessor flag called _VARIADIC_MAX which specifies the max number of arguments that you can pass to a variadic template , in GoogleTest`s case , this flag needs to be set to 10 : http://blogs.msdn.com/b/vcblog/archive/2011/09/12/10209291.aspx

1.Atomicity and lock-free programming : C++11 standards now brings a memory model which dictates how to access to the memory by the machine code produced by C++ compilers. And following this , you can now use atomic variables. In a nutshell, atomic variables are variables that it is guaranteed that they will not cause any data races. This allows us to implement lock-free multithreaded programming , which will be running faster than using kernel synchronisation objects like mutexes.

This is achieved by processor instructions support. So the difference from traditional variables is that Read-Modify-Write operations are done in an atomic way in CPU instruction level. This allows us to use thread-safe variables rather than expensive synchronisation objects like mutexes. Below you can see a quick benchmark of 2 counter variable implementations . The first one uses std::atomic and the latter uses std::mutex.

This benchmark was executed on :

– Linux Debian 3.2.0-4-amd64 #1 SMP Debian 3.2.63-2 x86_64 GNU/Linux
– Intel(R) Core(TM) i7-4700HQ CPU @ 2.40GHz
– Compiled with GCC 4.7

In the benchmark, std::mutex implementation took 31.583214414 seconds. On the other hand, std::atomic implementation took 9.685807040 seconds based on perf stat.

It also should be noted that  C++11 std::shared_ptr makes use of atomicity for reference counting. Therefore C++11 shared pointer`s reference counter is thread-safe.

Note for Windows systems: The Mutex class implemented by https://github.com/gekomad
Original source is on https://gist.github.com/gekomad/267b884dac64d4a4e68d
The idea is basically sticking with std::mutex for non-Windows systems  as by default they will be using futexes and stay in user mode as much as possible. That applies to GNU Lib C runtime, you can see futex usage if you strace. However for Windows side, it is not always the case that std::mutex will be implemented by using CRITICAL_SECTION

Regarding use of lightweight synchronisation objects : http://preshing.com/20111124/always-use-a-lightweight-mutex/

Regarding  MSVC CRT implementation : http://stackoverflow.com/questions/9997473/stdmutex-performance-compared-to-win32-critical-section

As Gekad informed , looks like Mingw on Windows does not also use CRITICAL_SECTION

2. Smart pointer support : By using C++11 memory header , you can use a various types of smart pointers :

a) auto_ptr deprecated and unique_ptr introduced : In C++03 was only offering auto_ptr, which was not compatible with STL containers since STL containers were copying objects and auto_ptrs invalidate a smart pointer when it is being copied. Therefore using [] operator to get a STL container element would NULL that element of your container.

unique_ptr is a better replacement for auto_ptr. It is a non-copyable class ( copy constructor and assignment operator are deleted ) and also it is a movable class that allows you safely to transfer the ownership of the underlying resource :

And by using move semantics with it , you can also move-push an object into an STL container via unique_ptr by avoiding copying of the object

Finally please note that there is no make_unique function unlike make_shared in C++11 , however this function will be there in C++14.

b) shared_ptr : Unlike unique_ptr which is only supposed to own one object at a time, shared_ptr underlying objects can be shared by many. This feature provided with a non-intrusive reference counting.

c) weak_ptr : This one can be seen as a support unit for shared_ptrs. They are particularly used to avoid cyclic references which happens when 2 classes used shared_ptrs pointing to each other. To experience this , you can use the code below. By turning on/off the flag USE_WEAKPTR , you can observe cyclic reference and weak_ptr`s affect :

3. Compile time features : C++11 gives us nice compile time features such as :

a) Const expressions : These are expressions forced to be computed in compile time :

If the expression can not be computed in compile time , then it will be evaluated during runtime. Note that you are limited to single function with only one return statement and you can not use branching/if-elses or loops. However as a workaround you can use ternary operators in C++11 constexpr functions :

b) Auto compile time type deduction : Auto variables` ( which will be described in usability sections ) type deduction is done in compile time. Therefore it is free to use auto variables.

c) Metaprogramming support with type traits : Type traits is a header that gives us information about types for template specialisation. That allows you specialise your templates based on type selection during compile time :

Below you can see another example , that also utilizes std::enable_if :

4. Less error prone coding :

a) Nullptr : nullptr is now a keyword and that solves the ambiguity problems of NULL since it was actually an integer :

b) Enum classes / Strongly typed enums : Now also enums won`t be treated as integers, but they will be type of their own :

c) Override keyword : When you write virtual functions, if the signature of the methods are different, this leads to create new functions rather than overriding a base class virtual method. By using override keyword for virtual methods, you invoke a compile time check. In C++03 :

In C++11 :

d) Curly brace initialisation : Curly brace initialisation can help you to identify narrowing or truncation errors during data conversions :

If you try to compile the code above with GCC , it will display an compilation error :

error: narrowing conversion of ‘1025’ from ‘int’ to ‘char’ inside { } [-Wnarrowing]

5. Usability features :

a) Auto : Auto keywords provides great flexibility when working with particularly templates classes such as STL iterators, smart pointers and many more. There is no runtime penalty to use auto variable as it is completely a compile time feature. The example below demonstrates that it makes it easier to declare std::shared_ptr smart pointers :

You can also look at next range based for loop example code to see how using auto makes it easier to work with STL iterators.

b) Range-based for loops : Now auto keyword can be used to store any type of variable and they can be used with range based , for-each like loop for every class that has begin() and end() methods. All STL containers and also std::array now support this :

You can also benefit from range based for loops by making your classes std::begin and std::end aware :

c) String literals: You can specify UTF8 UTF16 and UTF32 , however my favorite one is “raw” string literals. This can be particularly useful when creating connection strings and SQL queries. They allow you not needing using any escape characters , however keep in mind that using them can break your editor`s highlighting features :

d) std::function and std::bind : Especially useful when you write callback based applications. By using std::function/bind , you can avoid ugly function pointers and functors. You can see my related writing here :

https://nativecoding.wordpress.com/2015/02/08/learning-c11-lambda-expressions-and-stdfunction/

e) Lambda expressions : Related to previous item , they can be useful for particularly using STL algorithms. They can be used also to write quick thread/timer code. Again they can be seen in related writing here :

https://nativecoding.wordpress.com/2015/02/08/learning-c11-lambda-expressions-and-stdfunction/

f) STL Unordered containers : In STL , we had contiguous memory sequential containers ( vector, deque) , linked list sequential containers ( list ), associative and order-keeping

containers ( map, multimap, set, multiset) One of the most important features that has been added to STL is now unordered containers which internally implement hash tables.

Therefore that helps us not to look for a hash table / dictionary solution or implement one when we need constant time complexity for finding elements. ( As long as the performance doesn`t suffer from collisions ) . These new containers are :

unordered_map
unordered_multimap
unordered_set
unordered_multiset

g) Template aliases : You can now use using/typedef for template specialisation :

using StringDictionary = std::unordered_map<std::string>;

6. Threading library : This one is also nice if you don`t have very specific needs such as programmatically setting thread stack sizes. The provided features are :

Threads & system info : std::thread, std::thread::hardware_concurrency

Synchronisation primitives : std::mutex, std::condition_variable, std::recursive_mutex, std::timed_mutex

Deadlock detector : std::adopt_lock_t

Lock patterns : std::lock,  std::unique_lock, std::lock_guard

Thread local storage : thread_local

Others : std::once_flag , std::call_once

About std::shared_mutex : Unfortunately that will be available with C++17.

Note : There is also another parallel pattern supported in which you can use futures and promises.

As for examples showing how to use those , check my other “multithreading” related blog articles. Also here you can look at a full C++11 implementation of dining philosophers problem :

7. Others:

a) Move semantics : You can see my move semantics writing here :

https://nativecoding.wordpress.com/2015/02/08/learning-c11-move-semantics/

In my opinion , move semantics is not an absolutely must, however, it could be useful to optimise legacy codes that use STL containers.

b) STL Emplace methods: You can notice these new methods with some STL containers such as vector. C++11 takes advantage of move semantics with STL containers which help us to avoid deep copies but they do only shallow copies. Emplace methods take this to a further level and they don`t even invoke move constructors and assignment operators. Instead, they directly build objects in place ( inside the containers ).

c) Fixed width integers : Now cstdint.h is included in C++11 , therefore fixed width integers , which are actually typedefs , can be used easily. You can see my related article here :

https://nativecoding.wordpress.com/2015/01/11/notes-on-native-code-portability/

d) Thread safe local static variables : In C++11 local static variable initialisation is thread safe therefore this gives us a very cheap way of implementing thread safe singletons. On the other hand note that , that doesn`t apply to the implementation of MSVC : https://blogs.msdn.microsoft.com/oldnewthing/20040308-00/?p=40363/

AN INTERESTING SHORT CODE SNIPPET FEATURING MULTIPLE FEATURES

The code snippet above is Herb Sutter`s favourite as he stated. It is basically a thread safe cache implementation.

Advertisements

1 thought on “Transition to C++11 : The most important features”

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s