C++ Weekly #3: C++11 Key Features

C++11 Key Features

C++11 Overview

C++11 is the second major version of C++ (the previous one is C++98 and the next one is C++17) and the most important update since C++98. A large number of changes were introduced to both standardize existing practices and improve the abstractions available to the C++ programmers.

C++11 covered some of the most important language features that elevate the language to meet the modern language need. At the same time, it still maintained the most essential concepts that zero overhead in the design principle. For my experience, C++11 is the start of modern C++, it provides high-level abstraction but keep the absolute performance requirement. Now it gives the developer the option to write some clean and abstract code just as python and other high-level languages, at the same time, if we really need, we can still write code backward compatible to C or the C style to fulfill your low-level implementation needs. Such flexibility

I strongly recommend having a look at the detailed features on cppreference C++11 page.

Disclaimers: All the key features based on my personal experience. It may not cover all the language features that C++ standard committee guidelines. This is only my personal summary of the C++11 features, and the purpose of the blog more for study purpose and sharing the knowledge. If you have any opinion or suggestion on my summary, please feel free to leave a comment or email me directly.

auto

It is very useful when you don’t really need to worry about the return type. It cleans up your code and makes it easy to maintain and more readable. Also, it’s especially valuable when you doing generic programming.

template <typename Container, typename Value>
void count_value(const Container& c, const Value& v) {
  const auto count = std::count(begin(c), end(c), v);
}

Whether or not you follow the AAA(Almost Always Auto) idiom is up to your own preference, but I will mention it here for your own reference. For my own experience, AAA idiom make the modern C++ code style more consistent and solve some subtle issue. For more detail about AAA, please check Herb Sutter’s GotW #94 Solution: AAA Style (Almost Always Auto).

constexpr

constexpr make your code calculated and accessible at the compile time. This dramatically improves the performance of your codebase.

Although you will see the compile time increase, some of the computations could be done during its compilation. It’s absolutely worth the extra time spend especially for the C++ developer like you.

constexpr int sum_constexpr(int a, int b) {
    return a + b;
}

constexpr auto size = sum_constexpr(1, 2);

int main() {
    std::array<int, size> int_array;      // valid
}

constexpr was first introduced in C++11, it has some of the limitations during this version(have to be in a recursive fashion, branch prediction limitation, single return statement, etc.). however, most of issue or limitation was fixed in the later standard.

lambda expressions

Lambda is useful to replace the old way of writing the UnaryPredicate function. Those functions exist extensively in the C++ Algorithm library. We no longer need to write a separate function, also the UnaryPredicate could be in the same line with the algorithm calls. It also simplifies and cleans the code for all-purpose.

template <typename T> auto count_odd_number(const T &c) {
    const auto count = std::count_if(begin(c), end(c),
        [](const auto elem) { return elem % 2; });
    return count;
}

range-for loop

If you ever need to loop through each and every item in the loop, the range-for loop is almost always the way to go. It tight up the code and make the code not error-prone. The auto in the range-for loop also makes the generic programming much easier for a range-for loop.

template <typename T>
void call_on_elem(const T& container) {
    for(const auto& elem : container) {
        f(elem);
    }
}

smart pointer

The smart pointer now gives you the RAII fashion to do all the memory management. For object owning resources, I highly recommend you using smart pointers. For the modern C++ code, especially after C++14, you probably should never see new and delete in your codebase. It didn’t mean you should not know the under the hood memory management, as always if you really need, you can always manipulate the memory and do all your tweaks. Also, the smart pointer is not eliminating all the raw pointer and reference. Raw pointer and reference are great and use it whenever appropriate, for the case like passing object for the function call. But smart pointer gives you a much better tool to do all the owning pointer management.

C++98:

widget* factory();
void caller() {
    widget* w = factory();
    gadget* g = new gadget();
    use(*w, *g);
    delete g;
    delete w;
}

Modern C++:

unique_ptr<widget> factory();
void caller() {
    auto w = factory();
    auto g = make_unique<gadget>();
    use(*w, *g);
}

snippets credit: CppCon 2014: Herb Sutter “Back to the Basics! Essentials of Modern C++ Style”

I highly recommend you check out Sutter’s talk for more depth details.

honorable mentions

  • nullptr
  • default and delete function
  • final and override in inheritance
  • variadic templates
  • list initialization
Xuhui Sun
Xuhui Sun
Senior Software Engineer

Modern C++ enthusiast exploring Artificial Intelligence and Machine Learning. Passion for learning and sharing knowledge! ❤️