31
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel www.sela.co.il The Style of C++ 11 Sasha Goldshtein CTO, SELA Group blog.sashag.net | @goldshtn

The Style of C++ 11

Embed Size (px)

DESCRIPTION

SELA C++ Conference Keynote: The Style of C++ 11, by Sasha Goldshtein.

Citation preview

Page 1: The Style of C++ 11

© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israelwww.sela.co.il

The Style of C++ 11

Sasha GoldshteinCTO, SELA Group

blog.sashag.net | @goldshtn

Page 2: The Style of C++ 11

Agenda

C++11 status(Some) New language features(Some) New library featuresModern C++ style

Page 3: The Style of C++ 11

C++11 Status

• After more than a decade of contemplation . . .• ISO C++11 Standard was published in September 2011• Feature list: http://en.wikipedia.org/wiki/C%2B%2B11

• The Standard Library is part of the C++11 standard• Some new features are upstream merges from TR1

Page 4: The Style of C++ 11

C++11 Compiler Support

• Visual Studio 2010: Some features are supported• Visual Studio 2012: Some more features are supported

• Comparison chart between many other compilers: http://s.sashag.net/rpST0u

Visu

al S

tudi

o 20

10 Automatic variables, decltypeRvalue referencesLambda functions

Visu

al S

tudi

o 20

12 Concurrency libraryMemory model

Not

sup

port

ed y

et Variadic templatesCustom literalsDelegating constructors

Page 5: The Style of C++ 11

auto Variables

Implicit variable declaration: The compiler knows what you mean

(Almost) necessary for anonymous typesVery convenient for complex templatesEasily abused by lazy programmers!

std::map<...> M;auto iter = M.begin(); //what’s the type of iter?auto pair = std::make_pair(iter, M.key_range(...));auto lambda = []() { ... }; //lambdas have an anonymous typeauto ptr = condition ? new class1 : new class2; //ERRORauto x = 15; auto s = (string)"Hello"; //try to avoid...

Page 6: The Style of C++ 11

Range-Based for Loop

Automatic iterator over arrays and STL collectionsYour collection will work – provide begin(), end(), and an input iterator over the elementsUp to VC11 Beta: for each … in, a non-standard Microsoft extension

int numbers[] = ...;for (int n : numbers) std::cout << n;std::map<std::string,std::list<int>> M;for (const auto& pair : M)

for (auto n : pair.second)std::cout << pair.first << ' ' << pair.second;

Page 7: The Style of C++ 11

decltype

Use a compile-time expression instead of a type nameCan take the type of any expression

Very useful for templates, forwarding etc.

float arr[15];decltype(arr[0]) flt_ref = arr[0];decltype(arr[1]+7) flt;decltype(rand()) n = rand();

decltype(i+j) sum = i+j;

Page 8: The Style of C++ 11

Even More Fun with decltype

Your function can return a decltypeRequires special syntax in these examples because the return type depends on parameter types

template <typename T1, typename T2>auto multiply(const T1& t1, const T2& t2) -> decltype(t1+t2) {

return t1 * t2;}

template <typename InputIterator>auto nth_element(InputIterator iter, int n) -> decltype(*iter) {

while (--n > 0) ++iter;return *iter;

}

Page 9: The Style of C++ 11

Initializer Lists

Initialize arrays, lists, vectors, other containers—and your own containers—with a natural syntax

Not yet supported by Visual Studio 2012

vector<int> v { 1, 2, 3, 4 };list<string> l = { “Tel-Aviv”, “Jerusalem” };my_cont c { 42, 43, 44 };

class my_cont { public: my_cont(std::initializer_list<int> list) { for (auto it = list.begin(); it != list.end(); ++it) . . . }};

Page 10: The Style of C++ 11

Lambda Functions

int main() {[](){}();[]{}();} //this is legal C++, //although not useful

Page 11: The Style of C++ 11

Functors, bind, mem_fn, and Friends

The current state of function objects and operations on them leaves much to be desiredMust use arcane binding functions, placeholders, and rules to construct composite functors

class employee { public: void bonus(float commission, int vacation);};vector<int> employees;std::for_each(employees.begin(), employees.end(), std::bind(std::mem_fn(&employee::bonus), _1, 0.25f, 3));

Page 12: The Style of C++ 11

TR1 function<...>

TR1 makes it somewhat easier to manipulate functors (functions and classes with operator())Doesn’t make it easier to create functors

std::function<bool(int,int)> g = greater<int>();std::function<int(int,char**)> m = main;

std::function<bool(int)> greater_than17 = std::bind(g, _1, 17);

std::function<void(X*)> f = &X::foo; //foo is a member function

Page 13: The Style of C++ 11

Lambda Functions

Inline methods in other methods (closures)Compile to an anonymous class that serves as a function objectRich capture semantics by value and by reference

auto print_num = [](int n) { std::cout << n; };std::list<int> ns = ...;std::for_each(ns.begin(), ns.end(), print_num);int even = std::count_if(ns.begin(), ns.end(), [](int n) { return

n&1==0; });

int x = 5;[&x]() { ++x; }(); //capture by reference[ x]() { ++x; }(); //capture by value. doesn’t compile!!

Page 14: The Style of C++ 11

More Fun With Lambdas

Default capture (use at your own risk)Mutable lambdasExplicit return value

int fib1 = 1, fib2 = 1;auto next_step = [&]() { //default capture by reference

int temp = fib2; fib2 = fib2 + fib1; fib1 = temp;};for (int i = 0; i < 20; ++i) next_step();

int n = 10;auto say_yes_n_times = [=]() mutable ->bool { //default capture by

value,return (--n > 0); //mutable and returns bool

};

Page 15: The Style of C++ 11

Higher-Order Functions

std::function<...> to the rescueFreely manipulate lambdas as objects

auto identity = [](int x) {return [x]() { return x; };

};auto next = [](const std::function<int(void)>& lambda) {

return [&lambda]() { return lambda() + 1; };};auto _1 = identity(1);auto _2 = next(_1);auto _3 = next(_2);std::cout << _1() << _2() << _3();

Page 16: The Style of C++ 11

Converting and Designing Code to Use Lambdas

Recall our contrived bind(mem_fn(…)) exampleUse a lambda instead of composite functors

Design your APIs with lambdas in mind

std::for_each(employees.begin(), employees.end(), std::bind(memfn(&employee::bonus), _1, 0.25f, 3));std::for_each(employees.begin(), employees.end(), [](const employee& e) { e.bonus(0.25f, 3); });

template <typename Callback>void enum_windows(const string& title, Callback callback) { . . . callback(current_window);}//or, use const std::function<void(const window&)>& as parameter

Page 17: The Style of C++ 11

Rvalues and Lvalues—Reminder

Lvalues are values that have a nameCan appear on the left-hand-side of an assignment

Rvalues are the rest

int x;x = 42; //OK, x has a name, it’s an lvalue42 = x; //Obviously wrong, 42 does not have a name, it’s an

rvaluex + 2 = 42; //Also wrong, x + 2 returns a temporary, it’s an rvaluex++ = 42; //Also wrong, x++ returns a temporary, it’s an rvalue

int& foo();int* goo();--foo(); //OK, foo() returns an lvalue++(*goo()); //OK, a dereferenced pointer is an lvalue

Page 18: The Style of C++ 11

Who Cares?

Turns out, this “standard” approach to references limits the performance of the languageIn this example, the contents of the vectors are COPIED

void init_vector(vector<int>& v);

vector<int> v, w;init_vector(v); //no copy, we were careful to pass a referenceinit_vector(w); //no copy, we were careful to pass a reference

swap(v, w);//internally, swap will copy v to temp, w to v, temp to w, for a

total//of THREE MEMORY ALLOCATIONS AND DEALLOCATIONS!//but how can we tell swap (and vector) to MOVE the contents around?

Page 19: The Style of C++ 11

Rvalue References

Rvalue references are references to rvalues!Standard references are to lvalues, const references may refer to temporary rvaluesEnable move construction and assignment

my_array(const my_array& other) {//copy ctordataptr_ = new T[size_ = other.size_];memcpy_s(dataptr_, size_*sizeof(T), other.dataptr_, size_*sizeof(T));

}my_array& operator=(const my_array& other) { /*same deal*/ }my_array& operator=(my_array&& other) { //move assignment

dataptr_ = other.dataptr_; size_ = other.size_;other.dataptr_ = nullptr; other.size_ = 0;

}my_array(my_array&& other) { //move ctor

*this = std::move(other); //NOTE: && is lvalue in the method body}

Page 20: The Style of C++ 11

Why Rvalue References?

• Much fewer copies of temporary objects float around– E.g. consider std::vector<T> with reallocation– Huge performance boost when your types are used in STL– Huge performance boost when using strings and other types

with inner state that is expensive to copy

Page 21: The Style of C++ 11

Modern C++ Style

• Use auto, for each, initializer lists ubiquitously• Don’t be afraid of returning objects by value– RVO, NRVO, and move constructors will minimize copies

• OK to design algorithms that require predicates, projections, and other functors– They will be easy to use—with lambda functions

• Use STL algorithms more widely with lambdas

Page 22: The Style of C++ 11

Hash Tables

Four standard unordered containers which use hash tables as their implementation

unordered_map, unordered_set, unordered_multimap, unordered_multiset

set<string> names = { “Mike”, “Adam” };assert(*names.begin() == “Adam”);

unordered_set<string> names = { “John”, “Abe” };for (auto name : names) cout << name; //alphabetic order is NOT guaranteed

Page 23: The Style of C++ 11

Regular Expressions

PERL-style regular expression facility offered by std::regex class and associated functions

regex version("(\\d+)\\.(\\d+)\\.(\\d+)");string text = "2.0.50727";

cmatch captures;if (regex_search(text.c_str(), captures, version)) { cout << "Major: " << captures[0] << endl; cout << "Build: " << captures[2] << endl;}

//there’s also regex_replace for obvious purposes

Page 24: The Style of C++ 11

New Smart Pointers

• The standard library now has three types of smart pointers, eliminating the need to ever use delete

• If you are the sole owner of the object, use unique_ptr to make sure it’s deleted when the pointer dies (RAII)

• If you want to share the object with others, use shared_ptr—it will perform smart reference counting

• If you got yourself a cycle, use weak_ptr to break it!

Page 25: The Style of C++ 11

unique_ptr

Sole owner of an objectSupports move semantics, but not copy semantics

Replaces auto_ptr (which can’t move!)

unique_ptr<expensive_thing> create() { unique_ptr<expensive_thing> p(new expensive_thing); //...do some initialization, exceptions are covered by RAII return p;}

unique_ptr<expensive_thing> p = create(); //move constructor used!

//another example is storing pointers in containers:vector<unique_ptr<string>> v = { new string(“A”), new string(“B”) };

Page 26: The Style of C++ 11

shared_ptr

Thread-safe reference-counted pointer to an object with shared ownership

When the last pointer dies, the object is deleted

struct file_handle { HANDLE handle; file_handle(const string& filename) ... ~file_handle() ... //closes the handle};class file { shared_ptr<file_handle> _handle;public: file(const string& filename) : _handle(new file_handle(filename)) {} file(shared_ptr<file_handle> fh) : _handle(fh) {}}; //can have multiple file objects over the same file_handle

Page 27: The Style of C++ 11

weak_ptr

Points to a shared object but does not keep it alive (does not affect reference count)

The object may be destroyed “under our nose” at any time

Breaks cycles between shared_ptrs

class employee { weak_ptr<employee> _manager; vector<shared_ptr<employee>> _direct_reports;public: void beg_for_vacation(int days) { if (auto mgr = _manager.lock()) { mgr->beg(days); } //mgr is shared_ptr else { /* your manager has been eliminated :-) */ } }};

Page 28: The Style of C++ 11

Modern C++ Style

• Use smart pointers—no reason to have a delete statement in your code– If you’re the only owner, use unique_ptr– If you’re sharing the object, use shared_ptr– Create shared_ptrs with make_shared()– To prevent cycles, use weak_ptr

• Use the non-member begin() and end() functions– They work on arrays, and can be overloaded for types you

don’t control

Page 29: The Style of C++ 11

Summary

C++11 status(Some) New language features(Some) New library featuresModern C++ style

Page 30: The Style of C++ 11
Page 31: The Style of C++ 11

References

• Bjarne Stroustrup’s FAQ: http://s.sashag.net/vWT1eI• C++11 Wikipedia article: http://s.sashag.net/vdSCW3• What’s New in VC++ 10: http://s.sashag.net/tb1fnr• What’s New in VC++ 11: http://s.sashag.net/sXy26y• More on rvalue references: http://s.sashag.net/uVLJ23• STL11 preliminary docs: http://s.sashag.net/vWR7sW• C++ memory model: http://s.sashag.net/rqsoDW• Modern C++ style: http://s.sashag.net/rP5DFl