c++11: feel the new language

35
C++11 Feel the new language

Upload: mspline

Post on 26-May-2015

599 views

Category:

Technology


4 download

TRANSCRIPT

Page 1: C++11: Feel the New Language

C++11Feel the new language

Page 2: C++11: Feel the New Language

Where is C++?

Page 3: C++11: Feel the New Language

What’s special about C++

• Build abstractions at little or no cost• Without sacrificing transparency• Without sacrificing performance• Pay as you go• Dive under the hood whenever you like

Lightweight abstraction programming languageB.Stroustrup

Page 4: C++11: Feel the New Language

What makes C++11 different

Direct language support for powerful patterns Lambdas, move semantics

Incorporating best practices and libs into STL– Smart pointers, regular expressions

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

Shifting programming style to higher level– Naked pointers are persona non grata

E.g.

E.g.

E.g.

E.g.

Page 5: C++11: Feel the New Language

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

Page 6: C++11: Feel the New Language

Smart pointers and Resource Handling

Page 7: C++11: Feel the New Language

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

Page 8: C++11: Feel the New Language

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

…}

Page 9: C++11: Feel the New Language

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}

Page 10: C++11: Feel the New Language

shared_ptr<T>• Ref-counting semantics• Last one calls delete in destructor• Transparent and deterministic• Ref-counting and synchronization overhead• Use make_shared to reduce overhead• 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}

shared_ptr<T>

shared_ptr<T>

shared_ptr<T>

T

counter control block

Page 11: C++11: Feel the New Language

Resource Acquisition is Initializationvoid 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}

Page 12: C++11: Feel the New Language

• 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

Resource Acquisition is Initialization

Page 13: C++11: Feel the New Language

Tradeoff That Isn’t

Page 14: C++11: Feel the New Language
Page 15: C++11: Feel the New Language
Page 16: C++11: Feel the New Language
Page 17: C++11: Feel the New Language

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.

Page 18: C++11: Feel the New Language

Move Semantics

Page 19: C++11: Feel the New Language

Value semantics as copy semantics

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}

• 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

• Which requires ugly workaroundsvoid operator+( const Matrix& a, const Matrix& b, Matrix& r ){ // Loop with r[i,j] = a[i,j]+b[i,j]}

Page 20: C++11: Feel the New Language
Page 21: C++11: Feel the New Language
Page 22: C++11: Feel the New Language
Page 23: C++11: Feel the New Language

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; }};

Page 24: C++11: Feel the New Language

Move semantics

• Readable• Efficient• Safe• Meaningful• Backward-compatible• Fully supported by STL

Matrix m = a * transpose(b) + c * inv(d);

Page 25: C++11: Feel the New Language

Rvalue references

• 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

Matrix( const Matrix& other ); // const lvalue refMatrix( Matrix&& other ); // non-const rvalue ref

Page 26: C++11: Feel the New Language

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}

• ExplicitMatrix 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}

Page 27: C++11: Feel the New Language

Lambdas

λ

Page 28: C++11: Feel the New Language

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 );}

Page 29: C++11: Feel the New Language

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; } );}

Page 30: C++11: Feel the New Language

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.

Page 31: C++11: Feel the New Language

Lambda anatomy

lambda introducer

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

parameter listcapture list

return type

body

captured variable

Page 32: C++11: Feel the New Language

Lambda physiology

struct CompilerGeneratedFunctor{ int m_d; CompilerGeneratedFunctor(int d) : m_d(d) {} bool operator()(int n) const { return n % m_d == 0; }};

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

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

• For each lambda compiler generates a class

Page 33: C++11: Feel the New Language

Lambda physiology

bool CompilerGeneratedFunction(int n){ return n % 2 == 0;}

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

• Inlining is even easier

• Lambda with empty capture list is just a function

Page 34: C++11: Feel the New Language

Variable capture

[=][x, y, z]

By value[&][&x, &y, &z]

By reference[=, &x, &y][&, x, y]

Mix

Page 35: C++11: Feel the New Language

Recommended watching

http://channel9.msdn.com/Events/GoingNative/GoingNative-2012