the style of c++ 11
DESCRIPTION
SELA C++ Conference Keynote: The Style of C++ 11, by Sasha Goldshtein.TRANSCRIPT
![Page 1: The Style of C++ 11](https://reader035.vdocument.in/reader035/viewer/2022062513/554f707bb4c905c8088b553b/html5/thumbnails/1.jpg)
© 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](https://reader035.vdocument.in/reader035/viewer/2022062513/554f707bb4c905c8088b553b/html5/thumbnails/2.jpg)
Agenda
C++11 status(Some) New language features(Some) New library featuresModern C++ style
![Page 3: The Style of C++ 11](https://reader035.vdocument.in/reader035/viewer/2022062513/554f707bb4c905c8088b553b/html5/thumbnails/3.jpg)
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](https://reader035.vdocument.in/reader035/viewer/2022062513/554f707bb4c905c8088b553b/html5/thumbnails/4.jpg)
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](https://reader035.vdocument.in/reader035/viewer/2022062513/554f707bb4c905c8088b553b/html5/thumbnails/5.jpg)
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](https://reader035.vdocument.in/reader035/viewer/2022062513/554f707bb4c905c8088b553b/html5/thumbnails/6.jpg)
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](https://reader035.vdocument.in/reader035/viewer/2022062513/554f707bb4c905c8088b553b/html5/thumbnails/7.jpg)
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](https://reader035.vdocument.in/reader035/viewer/2022062513/554f707bb4c905c8088b553b/html5/thumbnails/8.jpg)
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](https://reader035.vdocument.in/reader035/viewer/2022062513/554f707bb4c905c8088b553b/html5/thumbnails/9.jpg)
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](https://reader035.vdocument.in/reader035/viewer/2022062513/554f707bb4c905c8088b553b/html5/thumbnails/10.jpg)
Lambda Functions
int main() {[](){}();[]{}();} //this is legal C++, //although not useful
![Page 11: The Style of C++ 11](https://reader035.vdocument.in/reader035/viewer/2022062513/554f707bb4c905c8088b553b/html5/thumbnails/11.jpg)
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](https://reader035.vdocument.in/reader035/viewer/2022062513/554f707bb4c905c8088b553b/html5/thumbnails/12.jpg)
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](https://reader035.vdocument.in/reader035/viewer/2022062513/554f707bb4c905c8088b553b/html5/thumbnails/13.jpg)
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](https://reader035.vdocument.in/reader035/viewer/2022062513/554f707bb4c905c8088b553b/html5/thumbnails/14.jpg)
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](https://reader035.vdocument.in/reader035/viewer/2022062513/554f707bb4c905c8088b553b/html5/thumbnails/15.jpg)
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](https://reader035.vdocument.in/reader035/viewer/2022062513/554f707bb4c905c8088b553b/html5/thumbnails/16.jpg)
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](https://reader035.vdocument.in/reader035/viewer/2022062513/554f707bb4c905c8088b553b/html5/thumbnails/17.jpg)
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](https://reader035.vdocument.in/reader035/viewer/2022062513/554f707bb4c905c8088b553b/html5/thumbnails/18.jpg)
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](https://reader035.vdocument.in/reader035/viewer/2022062513/554f707bb4c905c8088b553b/html5/thumbnails/19.jpg)
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](https://reader035.vdocument.in/reader035/viewer/2022062513/554f707bb4c905c8088b553b/html5/thumbnails/20.jpg)
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](https://reader035.vdocument.in/reader035/viewer/2022062513/554f707bb4c905c8088b553b/html5/thumbnails/21.jpg)
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](https://reader035.vdocument.in/reader035/viewer/2022062513/554f707bb4c905c8088b553b/html5/thumbnails/22.jpg)
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](https://reader035.vdocument.in/reader035/viewer/2022062513/554f707bb4c905c8088b553b/html5/thumbnails/23.jpg)
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](https://reader035.vdocument.in/reader035/viewer/2022062513/554f707bb4c905c8088b553b/html5/thumbnails/24.jpg)
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](https://reader035.vdocument.in/reader035/viewer/2022062513/554f707bb4c905c8088b553b/html5/thumbnails/25.jpg)
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](https://reader035.vdocument.in/reader035/viewer/2022062513/554f707bb4c905c8088b553b/html5/thumbnails/26.jpg)
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](https://reader035.vdocument.in/reader035/viewer/2022062513/554f707bb4c905c8088b553b/html5/thumbnails/27.jpg)
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](https://reader035.vdocument.in/reader035/viewer/2022062513/554f707bb4c905c8088b553b/html5/thumbnails/28.jpg)
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](https://reader035.vdocument.in/reader035/viewer/2022062513/554f707bb4c905c8088b553b/html5/thumbnails/29.jpg)
Summary
C++11 status(Some) New language features(Some) New library featuresModern C++ style
![Page 30: The Style of C++ 11](https://reader035.vdocument.in/reader035/viewer/2022062513/554f707bb4c905c8088b553b/html5/thumbnails/30.jpg)
![Page 31: The Style of C++ 11](https://reader035.vdocument.in/reader035/viewer/2022062513/554f707bb4c905c8088b553b/html5/thumbnails/31.jpg)
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