A Tour of C++

1. The Basics

  • Initialization

    double d1 = 2.3;
    double d2 {2.3};
    double d3 = {2.3}; complex<double> z = 1; complex<double> z2 {d1,d2}; complex<double> z3 = {d1,d2};
  • Use auto to have the compiler deduce the variable’s type:

  • Immutable values

    • const: value can be calculated at run time
    • constexpr: value must be calculated at compile time
    • 400
    • Expressions within a constexpr must themselves be constexprs
    • Functions can be constexpr too, but with restrictions
      • To be constexpr, a function must be rather simple and cannot have side effects and can only use information passed to it as arguments. In particular, it cannot modify non-local variables, but it can have loops and use its own local variables.
      • 400
  • Loops

    • Range over a collection:

      for (auto x : v)
          cout << x << '\n';
    • This copies each element of v into x though. To do this by reference instead:

      for (auto &x : v)
          cout << x << '\n';
  • Functions copy arguments by default, use explicit references to avoid this

    • Use const references to avoid copying when you don’t want to mutate args
  • nullptr, not NULL

  • if statements can introduce variables

    void do_something(vector<int>& v) {
        if (auto n = v.size(); n!=0) {
            // ...
  • 700

  • References vs. pointers

    • References appear to be like pointers but somewhat more ergonomic in that dereferencing is automatic
    • References can’t be reassigned after initialization
    • 700
    • 700
  • Initialization vs. assignment *

    In general, for an assignment to work correctly, the assigned-to object must have a value. On the other hand, the task of initialization is to make an uninitialized piece of memory into a valid object.

2. User-Defined Types


  • Initialization


  • Basic structure: 400
  • There is no fundamental difference between a struct and a class; a struct is simply a class with members public by default. For example, you can define constructors and other member functions for a struct.


  • The compiler doesn’t keep track of which union field is currently active, so unions are typically combined with a type enum, called a tagged union
  • Use variants to do this directly:
    variant<int, string> v = "abc";
    if (holds_alternative<int>(v)) {
    	// v is an int
    } else {
    	// v is a string


enum class Color { red, blue, green };
Color col = Color::red;

3. Modularity

  • Header files containing declarations but not implementations

    • 500
    • The use of #includes is a very old, error-prone, and rather expensive way of composing programs out of parts. If you #include header.h in 101 translation units, the text of header.h will be processed by the compiler 101 times. If you #include header1.h before header2.h the declarations and macros in header1.h might affect the meaning of the code in header2.h. If instead you #include header2.h before header1.h, it is header2.h that might affect the code in header1.h

  • Modules are a replacement that will be part of C++20

    • Only compiled once, even with multiple imports
    • Doesn’t need the header/impl split, control visibility from a single file
  • Namespaces

    • Use :: as an explicit namespace qualifier
    • using to bring a namespace into (lexical) scope
    • namespace to define a namespace/members
  • try/catch for error handling

    • Destructors are invoked as the call stack is unwound
    • Exceptions appear to all inherit from class Exception
    • Use the noexcept modifier for functions that should never throw (the process is terminated if the function throws)
  • The assert macro only performs assertions in “debug mode”

  • static_assert for compile-term assertions (argument must evaluate to a constexpr)

  • Does the act of passing a reference by value copy the reference itself or the target?

  • Return-by-reference either using pointers (bad form, apparently) or move constructors

  • Destructuring/binding struct args/returns:

    struct Entry {
    	string name;
    	int value;
    Entry foo() {
    	string s = "foobar";
    	int i = 0;
    	return {s, i};
    void bar(Entry e) {
    	auto [n, v] = e;

4. Classes