C++

C++ is a general-purpose, high-level, multi-paradigm programming language created by Bjarne Stroustrup at Bell Labs in 1979 by extending the C programming language. C++ is now represented with a number of ISO standards corresponding to the years 1998, 2003 (minor release), 2011, and 2014 usually referred to as C++98, C++03, C++11, and C++14. (The next C++ standard will likely become official in 2017 and for this reason is usually referred to as C++17.) If you are new to C++ or wish to read an overview of the language and/or how each ISO standard impacted it, check out the following Wikipedia links:

  1. C++, i.e., the language, history, and C++98.
  2. C++03: Minor release (mostly bug fixes). Mandates that std::vector stores its elements contiguously.
  3. C++11: Major release adding many new language and library features including concurrency (e.g., threads, atomics, compare-and-swap). See the link for details.
  4. C++14: While mostly bug fixes and small improvements, this version simplifies/generalizes the use of a number of constructs including constexpr, auto, lambdas (e.g., move capture).
  5. C++17: Soon-to-be-major release. Amongst other items, support for parallel STL algorithms will likely be included.

The most definitive, up-to-date, free online (wiki) reference for C++ (and its C Standard Library subset) is cppreference.com. This site also includes example code and tags definitions with the C++ standards to which they are defined / changed. Should you have a need to refer to the actual ISO standard document for C++, you can obtain a link to the last draft (which may well have errors in it!) before each ISO C++ standard release in that page's reference section. (If you need the official document, you may purchase it from Standards Council of Canada.)

ISO standards typically rely on other standards and C++ is no exception. The ISO C++ standards rely on the ISO C standards definitions (per the text, restrictions, etc. in the ISO C++ standard). For this reason it is useful to be aware of the various C standards that the ISO C++ standards refer to. C++98 relies on C90; C++11 and C++14 was standardized at the same time as C11 to ensure clean and clear definitions with respect to concurrency and memory models.

Well-Defined Concurrency and Memory Models

It is important to realize that prior to 2011 ISO C++ and ISO C standards these languages had no definitions of concurrency and corresponding memory model behaviour. In pre-C++11 / pre-C11 code, while most of the time the "right" thing is done, understand there are no guarantees with the language specifications (and therefore compiler implementations of such) of the ordering of reads and writes under concurrency. Ideally newly developed C++ and C concurrent code is explicitly compiled under C++11 and/or C11 settings to have and leverage well-defined concurrency and memory models' definitions. All concurrency and memory models in ISO C++ have a corresponding equivalent in ISO C. That said, most persons prefer easier-to-write-and-understand generic/object-based code, and would therefore prefer using C++ over C for concurrent.

Prior to C++11 and C11, one would have used the pthreads / Windows threading APIs to implement concurrency. Although many compilers will implement C++11 and C11 threads, etc. in terms of pthreads / Windows threading APIs, using the ISO C++11 and ISO C11 definitions is better for two reasons:

  • the code is compiler and platform independent, and,
  • C++11 and C11 have well-defined memory models --continuing to compile code using pre-C++11 and/or pre-C11 compiler language flags implies that no memory models are formally in effect (i.e., one is likely relying on undefined behaviour).

Compiler Support

Language Features

Various compilers implement various language features differently. Unfortunately a number of compilers only partially implement some of the ISO standard language feature requirements with each release of their compilers. This can sometimes make it frustrating when compiling code with a new compiler that does not yet implement a specific language feature. Fortunately there is a wiki page covering virtually all major C++ compilers and which compiler versions implement specific language features at cppreference.com. This page also provide links to each compiler's web site concerning the details of such.

Standard Library Implementation

It is important to realize that many C++ compilers under Linux do not actually provide their own implementation of the C++ Standard Library. Instead these compilers use one that is installed on the system. Typically this implies that libstdc++, which is distributed with GCC, is being used. This is important because outside of the C++ language itself nearly everything one uses is in the Standard Library, e.g., containers, algorithms, iostream, threads, random numbers, etc.

NOTE: While you need not worry about this, this is the reason C++ compilers other than GCC on systems across Compute Canada must be configured by the administrators to use the correct version of libstdc++ as several versions of GCC (and therefore libstdc++) are typically installed on the system. If such is set improperly, then there may be issues. This is also a reason why users should never hard-code explicit paths to administrator-installed libraries to, for example, compile software.

Nicely the GCC documentation has a section which details Standard Library components are supported in libstdc++.

Pitfalls

The volatile Keyword

The reader should note that volatile in C++ and C has a very specific meaning, e.g., see this page. Consequently using volatile in C/C++ code is a rare event --typically limited to certain kinds of low-level code.

Misuse of volatile might arise because the Java programming language uses the volatile keyword as well. Unfortunately, Java's volatile has a totally different meaning from volatile in C or C++. Specifically, Java's volatile keyword in C++ would correspond to using std::atomic<T> for some type T or std::atomic_* (i.e., the C library equivalents where '*' corresponds to a fundamental type name such as int).

NOTE: It is unlikely you will ever use the volatile keyword in any of your C++ code. In pre-ISO C++11 concurrent code you might need to use volatile but that would be a very rare event. Instead of volatile, always use the appropriate mutex, atomic, etc. features of the library you are using (e.g., pthreads, the C++ Standard Library).