A recommendation for C++11

Published on December 1, 2013
This article was written as the December 23 entry of the Competitive Programming Advent Calendar Div2013.

A recommendation for C++11

This is an introductory article for people who use C++03 on a daily basis but have never tried C++11. Recently, C++11 has been becoming available in many programming contests. C++11 makes C++ much easier to write, so please read this article and start using C++11! In this article, I introduce, among the many new features added in C++11, those that seem useful for contests (or that many people are likely to use).

How to run it locally

If you use GCC or clang, adding the -std=c++0x option enables the C++11 features.
$ g++ -std=c++0x -o program program.cc

The template right-shift problem

// In [C++03], >> is interpreted as a right shift and causes a compile error.
// In [C++11], vector<vector<int>> is correctly recognized.
vector<vector<int>> v;

nullptr

In C++03, NULL was defined as the int value 0. Because of this, in overload resolution it was preferentially treated as a number rather than a pointer, which sometimes caused unintended behavior. Therefore, C++11 introduced a value called nullptr of type nullptr_t. From now on, using nullptr is recommended.
// [C++03] used NULL, an int defined by a macro.
void* x = NULL;

// [C++11] provides nullptr of type nullptr_t.
void* x = nullptr;

initializer_list

initializer_list was introduced, making it easy to initialize containers such as vector and set.
vector<int> v = {1, 2, 3, 4, 5};
set<int> s = {1, 2, 3, 4, 5};
vector<vector<int>> v = {{1, 2, 3}, {4, 5, 6, 7}};
map<string, string> m = {{"hoge", "Hoge"}, {"piyo", "Piyo"}};

auto and decltype

In GCC you could do type inference by using __typeof, but in C++11 type inference became possible as a standard feature. __typeof is also available as standard under a different name, decltype.
// [C++03] The conventional way.
set::iterator x = a.begin();

// [GCC C++03] Using __typeof.
__typeof(a.begin()) x = a.begin();

// [C++11] Using decltype.
decltype(a.begin()) x = a.begin();

// [C++11] Using auto.
auto x = a.begin();

Qualifying auto

You can also apply qualifiers such as const or reference to auto.
string s = "hoge";

// A reference.
auto& x1 = s;

// A read-only reference.
const auto& x2 = s;

Type inference for a function's return value

In C++11 you cannot infer the type directly from the return value, but you can use decltype to determine a function's return type.
decltype(cos(0)) Function(double r) {
  return cos(r);
}
However, this cannot be rewritten as follows.
// r inside decltype is undefined, so this is an error.
decltype(cos(r)) Function(double r) {
  return cos(r);
}
For this, C++11 provides the following solution.
auto Function(double r) -> decltype(cos(r)) {
  return cos(r);
}

range-based for

Until now, many competitive programmers prepared macros such as FOREACH to manipulate the elements of a vector or set, but C++11 added a feature called range-based for, allowing this to be written very simply.
// [C++03] The standard way.
set<int> a;
for (set<int>::iterator iter = a.begin(); iter != a.end(); iter++) {
  std::cout << *iter << std::endl;
}

// [GCC C++03] Defining a FOREACH macro using __typeof.
#define FOREACH(iter, a) \
    for (__typeof((a).begin()) iter = (a).begin(); iter != (a).end(); iter++)
set<int> a;
FOREACH(iter, a) {
  std::cout << *iter << std::endl;
}

// [C++11] Using range-based for.
set<int> a;
for (int i : a) {
  std::cout << i << std::endl;
}

// [C++11] Using auto together with range-based for.
set<int> a;
for (auto i : a) {
  std::cout << i << std::endl;
}

unique_ptr

An object created with new must be deleted without fail, or it becomes a source of memory leaks, but up to C++03 the standard offered no solution for this. For example, as in the following code, it was common to forget to delete a newed object when returning from a function or breaking out of a for loop.
void FunctionA() {
  ClassA* object_a = new ClassA;

  object_a->MethodA();
  if (...) {
    object_a->MethodB();
    // If you return here, on the path that goes through here you cannot delete, and a memory leak occurs.
    return;
  }

  delete object_a;
}
Replacing this with C++11's unique_ptr yields the following code, and you almost never accidentally cause a memory leak.
#include <memory>

void FunctionA() {
  std::unique_ptr<ClassA> object_a(new ClassA);

  object_a->MethodA();
  if (...) {
    object_a->MethodB();
    // Even if you return here, it is automatically deleted internally.
    return;
  }

  // With unique_ptr, there is no need to delete explicitly.
}

Advantages of unique_ptr

unique_ptr does not consume any extra memory. Its specification is simply to delete the contents, if they are not nullptr, when execution leaves the scope containing the variable. Empirically, most code that needs pointers can be replaced with unique_ptr. Code written with unique_ptr not only avoids the need for space for a reference counter, but also allocates memory when needed and releases it as soon as it is no longer needed, so it becomes very memory-efficient code. Moreover, there is no need to run extra processing such as mark-and-sweep, so it is also very efficient in terms of computational resources.

Correspondence with ordinary pointers

Declaring a variable

You declare a variable by passing a pointer to the constructor as shown below. If you do not need to initialize it with a pointer at first, you can also declare it as is.
// When you have a pointer to give.
ClassA* object_a = new ClassA;
std::unique_ptr<ClassB> object_b(new ClassB);

// When you have no pointer to give.
ClassA* object_a = nullptr;
std::unique_ptr<ClassB> object_b;

Calling a method

unique_ptr can be accessed with -> just like an ordinary pointer. However, it does not check whether object_b has contents (whether it is nullptr), so that remains the user's responsibility as before.
object_a->Method();
object_b->Method();

Dereferencing (materializing the pointer)

The dereference operator, like a method call, can be accessed just like an ordinary pointer.
(*object_a).Method();
(*object_b).Method();

Obtaining the pointer

An ordinary pointer is itself a pointer, but with unique_ptr you obtain the pointer using the get() method. get() does not transfer ownership, so the lifetime of the contents of that pointer continues to be managed by the unique_ptr object.
if (object_a == nullptr) return;
if (object_b.get() == nullptr) return;

Releasing ownership

The release() method releases ownership and sets the internal pointer to nullptr.
return object_a;
retrun object_b.release();

Overwriting the pointer

The reset() method deletes the internal pointer if necessary and replaces it with a new pointer.
if (object_a) delete object_a; object_a = new ClassA;
object_b.reset(new ClassB);

shared_ptr

unique_ptr cannot manage a pointer in multiple places. When you need to do so, you can use another smart pointer called shared_ptr. shared_ptr holds a reference counter internally, allowing the smart pointer to be copied. However, the situations where shared_ptr is truly needed should be very rare, so try not to overuse it.

array

C++11 added array so that fixed-length arrays can be handled in the same way as vector and the like. It provides begin(), end(), size(), and so on, so fixed-length arrays can be passed to functions and methods generalized with templates.
array<int, 5> a = {1, 2, 3, 4, 5};

template<typename Container> Reverse(Container* container) {
  reverse(container->begin(), container->end());
}

Reverse(a);

emplace, emplace_back

C++11 added methods such as emplace_back to vector and others. They look very similar to push_back and insert, but differ in that you pass the arguments rather than an actual object. Because the arguments are passed directly, no copy occurs.
vector<int> a = {1, 2, 3};
vector<vector<int>> b;

// Almost equivalent to b.push_back(vector<int>(a.begin(), a.end()));
b.emplace_back(a.begin(), a.end());

rvalue reference, move

C++11 added the concept of rvalue references to types. An rvalue reference variable explicitly indicates that its contents have been thrown away and thus do not need to be copied.
vector<vector<int>> a;
for (int i = 0; i < 1000; i++) {
  vector<int> b;
  for (int j = i; 0 < j; j--) {
    b.push_back(j);
  }
  // If optimization does not kick in well, a copy of b occurs here.
  a.push_back(b);
}

vector<vector<int>> a;
for (int i = 0; i < 1000; i++) {
  vector<int> b;
  for (int j = i; 0 < j; j--) {
    b.push_back(j);
  }
  // No copy of b occurs (it is reused).
  a.push_back(std::move(b));
  // However, you must not use the contents of b after this.
}

Useful links