C++11
Feel the new language
Where is C++?
What’s special about C++
    Lightweight abstraction programming language
                                          B.Stroustrup


•   Build abstractions at little or no cost
•   Without sacrificing transparency
•   Without sacrificing performance
•   Pay as you go
•   Dive under the hood whenever you like
What makes C++11 different
Direct language support for powerful patterns
  E.g.   Lambdas, move semantics
Incorporating best practices and libs into STL
  – Smart pointers, regular expressions
  E.g.



Catch-up with the modern hardware
  – Multi-threaded memory model
  E.g.



Shifting programming style to higher level
  – Naked pointers are persona non grata
  E.g.
What is a lightweight abstraction?
goto:
  – Low-level (machine thinking)
  – Welcome to spaghetti code

if-then-else, while-loop, loop-until:
  –   Abstracise goto
  –   High-level, meaningful (human thinking)
  –   Composable, self-contained building blocks
  –   Transparent
  –   No performance cost
  –   Can still use goto if necessary
Smart pointers and Resource
         Handling
Lightweight abstraction: memory
Raw pointers (T*):
  – Low-level (machine thinking)
  – Welcome to crashes and memory leaks


Smart pointers (unique_ptr<T>, shared_ptr<T>):
  –   Abstracise raw pointers
  –   High-level, meaningful (human thinking)
  –   Transparent
  –   Little or no performance cost
  –   Can still use raw pointers if necessary
Raw pointers (or HANDLEs)

widget *getWidget();
void foo()
{
    widget *pw = getWidget();
    // Don’t know if we’re sharing the widget with someone else
    // Don’t know if we must delete pw when done
    // Have to manually take care about exception-safety
    …
}
unique_ptr<T>
•   Ownership semantics
•   Think auto_ptr<T> done right
•   Calls delete or delete[] in destructor
•   Movable, but not copyable (see Move Semantics later)
•   No runtime overhead

#include <memory>
std::unique_ptr<widget> getWidget();
void foo()
{
    std::unique_ptr<widget> pw{ getWidget() };
    // The widget is exclusively ours
    // We can’t accidentally share it
    // It will be deleted automatically and exception-safe
}
shared_ptr<T>
•   Ref-counting semantics                    shared_ptr<T>        T


•   Last one calls delete in destructor
•   Transparent and deterministic             shared_ptr<T>

•   Ref-counting and synchronization overhead
•   Use make_shared to reduce overhead        shared_ptr<T>
                                                              counter
                                                              control block
•   Use weak_ptr to break cycles

#include <memory>
std::shared_ptr<widget> getWidget();
void foo()
{
    std::shared_ptr<widget> pw{ getWidget() };
    // The widget may be shared
    // We don’t own it so we don’t care about deleting it
}
Resource Acquisition is Initialization
void f()
{
    database *pdb = open_database("mydb");
    … // What if we return or throw here?
    close_database(pdb);
}




class DBConnection
{
private:
    database *_pdb;
public:
    explicit DBConnection(const char *name) : pdb(open_database(dbname)) {}
    ~DBConnection() { close_database(pdb); }
}
void f()
{
    DBConnection dbc("mydb");
    … // The db connection is guaranteed to close properly
}
Resource Acquisition is Initialization
• GC in other languages only handles one
  resource - memory
• RAII in C++ has been around for over a decade
• C++11 encourages its use as default
• Smart pointers help building RAII around
  legacy interfaces
• Move semantics makes passing resources
  around cheap
Tradeoff That Isn’t
What’s wrong with low-level?
•    Unsafe? – Yes
•    Tedious? – Yes
•    Gets in the way of DRY? – Yes
•    Best performance? – No. May even make it worse

    Low-level programming is a powerful and
    complex tool, but it doesn’t guarantee you any
    advantage unless used properly.
Move Semantics
Value semantics as copy semantics
• Value semantics traditionally means copy-semantics
• Which means object gets copied when travels from one
  place to another
• Which makes returning an object from a function expensive
 Matrix operator+( const Matrix& a, const Matrix& b )
 {
     Matrix r;
     // Loop with r[i,j] = a[i,j]+b[i,j]
     return r; // Copying happens here – expensive
 }

• Which requires ugly workarounds
 void operator+( const Matrix& a, const Matrix& b, Matrix& r )
 {
     // Loop with r[i,j] = a[i,j]+b[i,j]
 }
Move constructor (and =)
template <typename T> class Matrix
{
private:
    unsigned int m; // Number of rows
    unsigned int n; // Number of columns
    T *pelems;      // Pointer to an array of m*n elements
public:
    …
     // Copy constructor
     Matrix( const Matrix& other ) : m(other.m), n(other.n)
     {
         pelems = new T[m*n];
         memcpy( pelems, other.pelems, m*n*sizeof(T) );
     }
     // Move constructor
     Matrix( Matrix&& other )
     {
         pelems = other.pelems;
         other.pelems = nullptr;
     }
     ~Matrix(){ delete[] pelems; }
};
Move semantics
         Matrix m = a * transpose(b) + c * inv(d);



•   Readable
•   Efficient
•   Safe
•   Meaningful
•   Backward-compatible
•   Fully supported by STL
Rvalue references
 Matrix( const Matrix& other ); // const lvalue ref
 Matrix( Matrix&& other );      // non-const rvalue ref



• The right function is selected through overload
  resolution
• Rvalue reference is preferred when called with rvalue
• Non-constness of the rvalue reference allows to modify
  the rvalue
• Bonus: perfect forwarding
Copy or Move?
• Implicit
  Matrix f( const Matrix& a )
  {
      Matrix r(a); // copy: a can be used below, don’t mess with it
      …
      return r;    // move: r is on its last leg
  }


• Explicit
  Matrix f()
  {
      Matrix e{ {1,0}, {0,1} };
      Matrix r( std::move(e) ); // forced move: e is zombie now and
      …                         // using it would be a bad idea
  }
Lambdas



  λ
Life before lambdas
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
struct DivisibilityPredicateFunctor
{
    int m_d;
    DivisibilityPredicate( int d ) : m_d(d) {}
    bool operator()( int n ) const { return n % m_d == 0; }
};
void OutputFunction( int n )
{
    cout << n << endl;
};
vector<int> remove_multiples( vector<int> v, int d )
{
    vector<int> r;
    remove_copy_if( begin(v), end(v), back_inserter(r), DivisibilityPredicateFunctor(d) );
    return r;
}
void main()
{
    vector<int> v;
    int array[] = {0,1,2,3,4,5,6,7,8,9};
    for( int i = 0; i < sizeof array/sizeof *array; ++i )
        v.push_back( array[i] );
    vector<int> m = remove_multiples( v, 3 );
    for_each( begin(m), end(m), OutputFunction );
}
Life in C++11
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
vector<int> remove_multiples( vector<int> v, int d )
{
    vector<int> r;
    remove_copy_if( begin(v), end(v), back_inserter(r), [=](int n){ return n % d == 0; } );
    return r;
}
void main()
{
    vector<int> m = remove_multiples( {0,1,2,3,4,5,6,7,8,9}, 3 );
    for_each( begin(m), end(m), [](int n){ cout << n << endl; } );
}
Lambdas
• Without jumping through hoops now:
   – STL algorithms
   – Callbacks
   – Threading
• Foundation for higher-level stuff:
   – Async programming
   – Functional programming

C++ flavor: you have fine-grained control over
environment capture.
Lambda anatomy
                            return type
  lambda introducer                       captured variable



     [=] (int n) -> int { return n % d == 0; }

               parameter list
capture list                                     body
Lambda physiology
  • For each lambda compiler generates a class
                         struct CompilerGeneratedFunctor
                         {
[d](int n)->bool             int m_d;
{                            CompilerGeneratedFunctor(int d) : m_d(d) {}
                             bool operator()(int n) const
    return n % d == 0;       {
}                                return n % m_d == 0;
                             }
                         };



 • Specifying lambda instantiates an object
 • Invoking lambda calls the object’s operator()
 • Everything is easily inlinable
Lambda physiology

  • Lambda with empty capture list is just a function

[](int n)->bool          bool CompilerGeneratedFunction(int n)
{                        {
    return n % 2 == 0;       return n % 2 == 0;
                         }
}




 • Inlining is even easier
Variable capture


By value      By reference       Mix
[=]             [&]            [=, &x, &y]
[x, y, z]       [&x, &y, &z]   [&, x, y]
Recommended watching
http://channel9.msdn.com/Events/GoingNative/GoingNative-2012

C++11: Feel the New Language

  • 1.
  • 2.
  • 3.
    What’s special aboutC++ Lightweight abstraction programming language B.Stroustrup • Build abstractions at little or no cost • Without sacrificing transparency • Without sacrificing performance • Pay as you go • Dive under the hood whenever you like
  • 4.
    What makes C++11different Direct language support for powerful patterns E.g. Lambdas, move semantics Incorporating best practices and libs into STL – Smart pointers, regular expressions E.g. Catch-up with the modern hardware – Multi-threaded memory model E.g. Shifting programming style to higher level – Naked pointers are persona non grata E.g.
  • 5.
    What is alightweight abstraction? goto: – Low-level (machine thinking) – Welcome to spaghetti code if-then-else, while-loop, loop-until: – Abstracise goto – High-level, meaningful (human thinking) – Composable, self-contained building blocks – Transparent – No performance cost – Can still use goto if necessary
  • 6.
    Smart pointers andResource Handling
  • 7.
    Lightweight abstraction: memory Rawpointers (T*): – Low-level (machine thinking) – Welcome to crashes and memory leaks Smart pointers (unique_ptr<T>, shared_ptr<T>): – Abstracise raw pointers – High-level, meaningful (human thinking) – Transparent – Little or no performance cost – Can still use raw pointers if necessary
  • 8.
    Raw pointers (orHANDLEs) widget *getWidget(); void foo() { widget *pw = getWidget(); // Don’t know if we’re sharing the widget with someone else // Don’t know if we must delete pw when done // Have to manually take care about exception-safety … }
  • 9.
    unique_ptr<T> • Ownership semantics • Think auto_ptr<T> done right • Calls delete or delete[] in destructor • Movable, but not copyable (see Move Semantics later) • No runtime overhead #include <memory> std::unique_ptr<widget> getWidget(); void foo() { std::unique_ptr<widget> pw{ getWidget() }; // The widget is exclusively ours // We can’t accidentally share it // It will be deleted automatically and exception-safe }
  • 10.
    shared_ptr<T> • Ref-counting semantics shared_ptr<T> T • Last one calls delete in destructor • Transparent and deterministic shared_ptr<T> • Ref-counting and synchronization overhead • Use make_shared to reduce overhead shared_ptr<T> counter control block • Use weak_ptr to break cycles #include <memory> std::shared_ptr<widget> getWidget(); void foo() { std::shared_ptr<widget> pw{ getWidget() }; // The widget may be shared // We don’t own it so we don’t care about deleting it }
  • 11.
    Resource Acquisition isInitialization void f() { database *pdb = open_database("mydb"); … // What if we return or throw here? close_database(pdb); } class DBConnection { private: database *_pdb; public: explicit DBConnection(const char *name) : pdb(open_database(dbname)) {} ~DBConnection() { close_database(pdb); } } void f() { DBConnection dbc("mydb"); … // The db connection is guaranteed to close properly }
  • 12.
    Resource Acquisition isInitialization • GC in other languages only handles one resource - memory • RAII in C++ has been around for over a decade • C++11 encourages its use as default • Smart pointers help building RAII around legacy interfaces • Move semantics makes passing resources around cheap
  • 13.
  • 17.
    What’s wrong withlow-level? • Unsafe? – Yes • Tedious? – Yes • Gets in the way of DRY? – Yes • Best performance? – No. May even make it worse Low-level programming is a powerful and complex tool, but it doesn’t guarantee you any advantage unless used properly.
  • 18.
  • 19.
    Value semantics ascopy semantics • Value semantics traditionally means copy-semantics • Which means object gets copied when travels from one place to another • Which makes returning an object from a function expensive Matrix operator+( const Matrix& a, const Matrix& b ) { Matrix r; // Loop with r[i,j] = a[i,j]+b[i,j] return r; // Copying happens here – expensive } • Which requires ugly workarounds void operator+( const Matrix& a, const Matrix& b, Matrix& r ) { // Loop with r[i,j] = a[i,j]+b[i,j] }
  • 23.
    Move constructor (and=) template <typename T> class Matrix { private: unsigned int m; // Number of rows unsigned int n; // Number of columns T *pelems; // Pointer to an array of m*n elements public: … // Copy constructor Matrix( const Matrix& other ) : m(other.m), n(other.n) { pelems = new T[m*n]; memcpy( pelems, other.pelems, m*n*sizeof(T) ); } // Move constructor Matrix( Matrix&& other ) { pelems = other.pelems; other.pelems = nullptr; } ~Matrix(){ delete[] pelems; } };
  • 24.
    Move semantics Matrix m = a * transpose(b) + c * inv(d); • Readable • Efficient • Safe • Meaningful • Backward-compatible • Fully supported by STL
  • 25.
    Rvalue references Matrix(const Matrix& other ); // const lvalue ref Matrix( Matrix&& other ); // non-const rvalue ref • The right function is selected through overload resolution • Rvalue reference is preferred when called with rvalue • Non-constness of the rvalue reference allows to modify the rvalue • Bonus: perfect forwarding
  • 26.
    Copy or Move? •Implicit Matrix f( const Matrix& a ) { Matrix r(a); // copy: a can be used below, don’t mess with it … return r; // move: r is on its last leg } • Explicit Matrix f() { Matrix e{ {1,0}, {0,1} }; Matrix r( std::move(e) ); // forced move: e is zombie now and … // using it would be a bad idea }
  • 27.
  • 28.
    Life before lambdas #include<vector> #include <algorithm> #include <iostream> using namespace std; struct DivisibilityPredicateFunctor { int m_d; DivisibilityPredicate( int d ) : m_d(d) {} bool operator()( int n ) const { return n % m_d == 0; } }; void OutputFunction( int n ) { cout << n << endl; }; vector<int> remove_multiples( vector<int> v, int d ) { vector<int> r; remove_copy_if( begin(v), end(v), back_inserter(r), DivisibilityPredicateFunctor(d) ); return r; } void main() { vector<int> v; int array[] = {0,1,2,3,4,5,6,7,8,9}; for( int i = 0; i < sizeof array/sizeof *array; ++i ) v.push_back( array[i] ); vector<int> m = remove_multiples( v, 3 ); for_each( begin(m), end(m), OutputFunction ); }
  • 29.
    Life in C++11 #include<vector> #include <algorithm> #include <iostream> using namespace std; vector<int> remove_multiples( vector<int> v, int d ) { vector<int> r; remove_copy_if( begin(v), end(v), back_inserter(r), [=](int n){ return n % d == 0; } ); return r; } void main() { vector<int> m = remove_multiples( {0,1,2,3,4,5,6,7,8,9}, 3 ); for_each( begin(m), end(m), [](int n){ cout << n << endl; } ); }
  • 30.
    Lambdas • Without jumpingthrough hoops now: – STL algorithms – Callbacks – Threading • Foundation for higher-level stuff: – Async programming – Functional programming C++ flavor: you have fine-grained control over environment capture.
  • 31.
    Lambda anatomy return type lambda introducer captured variable [=] (int n) -> int { return n % d == 0; } parameter list capture list body
  • 32.
    Lambda physiology • For each lambda compiler generates a class struct CompilerGeneratedFunctor { [d](int n)->bool int m_d; { CompilerGeneratedFunctor(int d) : m_d(d) {} bool operator()(int n) const return n % d == 0; { } return n % m_d == 0; } }; • Specifying lambda instantiates an object • Invoking lambda calls the object’s operator() • Everything is easily inlinable
  • 33.
    Lambda physiology • Lambda with empty capture list is just a function [](int n)->bool bool CompilerGeneratedFunction(int n) { { return n % 2 == 0; return n % 2 == 0; } } • Inlining is even easier
  • 34.
    Variable capture By value By reference Mix [=] [&] [=, &x, &y] [x, y, z] [&x, &y, &z] [&, x, y]
  • 35.