Download presentation
Presentation is loading. Please wait.
Published byShawn Short Modified over 9 years ago
1
Gian Lorenzo Meocci 7 Febbraio Pordenone – C++ Community Meetup
C++11/14 Overview Gian Lorenzo Meocci 7 Febbraio Pordenone – C++ Community Meetup
2
Era il 1998 … Veniva approvato il C++98 …
Marco Pantani vinceva il Giro d’Italia e il Tour de France Gli Aerosmith cantavano “I Don't Want to Miss a Thing” Page e Brin, dell'Università di Stanford, fondavano Veniva approvato il C++98 …
3
Introduction Easy to teach Backward compatibility Performance
Surprisingly, C++11 feels like a new language: The pieces just fit together better than they used to and I find a higher-level style of programming more natural than before and as efficient as ever. Bjarne Stroustrup Goal of C++11/14 Easy to teach Backward compatibility Performance Productivity
4
Introduction: some numbers
~41 changes (and new features) to the core language ~27 changes to STL new components for STL (like regex) Big impact features: auto / range for movability (rvalue ref) lambdas unique_ptr & shared_ptr Uniform Initializer list * Try to write it using std algorithm!
5
Which was the feature of new C++ that improved the most your productivity? (Meetup Bologna)
6
ZIP function (our mascot)
Let me introduce the zip function. This function takes two list and pairs elements from the first list with the elements from the second list. zip :: [a] -> [b] -> [(a, b)] zip _ [] = [] zip [] _ = [] zip (x:xs) (y:ys) = (x, y) : zip xs ys Our goal is to implement it in C++14! Haskell Implementation ZIP 1 2 3 4 5 6 1, A 2, B 3, C A B C Thanks to lisperati.com
7
Type Inference: auto La moda passa, lo stile resta (Coco Chanel) auto is a placeholder for a type. Let the compiler deduce the correct one for you! In general, we can write: auto x = expression; and the type of x will be the type of the value computed from "expression". auto x = 27; auto f = 5.4f; auto s = "hello world!"; const auto x = 42; auto& y = x; auto t = &x; auto z = y; // x is an int // f is a float // s is a const char* // x is an const int // y is a ref to a const int // t is an const int* // z is an int! *see template deduction rule The auto feature has the distinction to be the earliest to be suggested and implemented in 1984!
8
auto & range for C++98 C++11 int r = 0;
Ok but the things became more interesting when apply to something more complex int r = 0; for (vector<int>::const_iterator it = v.begin(); it != v.end(); ++it) { if (*it % 2 == 0) r++; } C++98 Quite tedious!. The only interesting part is the check inside int r{}; // uniform initialization here for (const auto &e : v) { if (e % 2 == 0) r++; } C++11
9
auto & range for C++11 C++11 C++17?
Using range for int r{}; // uniform initialization here for (const auto &e : v) { if (e % 2 == 0) r++; } C++11 Prefer standard algorithm to raw loop! But we can use even an STL algorithm const int r = count_if (v.begin(), v.end(), [](const int& e) { return e % 2 == 0; }); C++11 const int r = count_if ( v , [](const auto& e) { return e % 2 == 0; }); C++17?
10
Uniform Initialization
In C++ we’ve different way to initialize basic and user defined type. C++11 introduce a new way to make initialization of various type more uniform. // GOOD news: struct Point {int x, y;} Point p {1, 5}; Point p{}; // fix most vexing parser double d{3.5}; vector<int> v{1, 2, 3, 4, 5}; int n {5.6}; // error: narrowing! int x{42}; //fine: no narrowing // but the following still to be valid! int x (0); int y = 0; // these are synonymous (**) int z{}; int z {0}; int z = {0}; //but pay attention with auto! auto r {6}; //std::inizializer_list<int> (*) auto r = int{6}; // fine: now r is 6 * Will be fixed in C++17, ** not valid for user-defined types with explicit constructors See: Back to the Basics! Essentials of Modern C++ Style - Herb Sutter - CppCon 2014
11
Uniform & In Class Initialization
We can use uniform initialization to initialize non-static data member “inline” and inside ctr. struct Widget { int x{ 0 }; // fine, x's default value is 0 int y = 0; // also fine int z(0); // error! Widget* child{nullptr}; };
12
decltype: writing generic code
template <typename A, typename B> (???) mult (A a, B b) { return a * b; } C++98 Quite impossible to express it in C++98 template <typename A, typename B> auto mult (A a, B b) -> decltype(a * b) { return a * b; } C++11 auto + decltype + traling return type
13
decltype: writing generic code
template <typename A, typename B> auto mult (A a, B b) -> decltype(a * b) { return a * b; } C++11 template <typename A, typename B> auto mult (A a, B b) { return a * b; } // or decltype(auto) mult (A a, B b) { return a * b; } (can be read as: put here the type decltype would have deduced) C++14 auto + decltype + traling return type
14
decltype & auto const int i = 0; // decltype(i) is an const int
decltype is an odd creature: it takes an expression (at compile time) and gives you a type! But we are taking about C++ so decltype doesn’t follow auto type deduction rules. const int i = 0; struct Point {int x, y;} decltype( f) b; struct A { int& f(int index) { return v[index]; } vector<int> v; } A e; auto x = e.f(); decltype(auto) y = e.f(); // decltype(i) is an const int // decltype(Point::x) is a int // b is a float put here the type decltype would have deduced // x is an int // y is an int&
15
See Marco Arena talk: (CDays 2014 Roma):
Movability “Move semantics makes it possible for compilers to replace expensive copying operations with less expensive moves.” (EMC++) vector<int> getVeryBigVector() { vector<int> r; // fill r with some cool algorithm … return r; } vector<int> mydata = getVeryBigVector(); // C++98 call copy assignment* * Assume no RVO See Marco Arena talk: (CDays 2014 Roma):
16
Movability: (implicit)
vector<int> getVeryBigVector() { vector<int> r{}; // fill r with some cool algorithm … return r; //implicit std::move } vector<int> mydata = getVeryBigVector(); // C++11 call move constructor temp obj
17
Movability: in our class
Double free or corruption!
18
Movability: follow the white rabbit
HeapContainer<int> (42) f() HeapContainer<int> x = f(); HeapContainer::(HeapContainer&& rs) f() ; //destroy rs temp x._data x._data is not valid
19
Movability: in our class
20
Movability: std::move & std::forwad
template <typename T> decltype(auto) move (T&& param) { using ReturnType = remove_reference_t<T>&&; return static_cast<ReturnType>(param); } Unconditional Cast Unconditionally casts its argument to an rvalue. template <typename T> T&& forward (remove_reference_t<T>& param) { return static_cast<T&&>(param); } Conditional Cast Cast to an rvalue only if its argument was initialized to an rvalue.
21
Movability: the swap function
template <typename T> inline void swap(T& a, T& b) { T tmp(a); a = b; b = tmp; } template <typename T> inline void swap(T& a, T& b) { T tmp {std::move(a)}; a = std::move(b); b = std::move(tmp); } C++98 C++11 3 copies! 3 (*) moves! * Note that for those types that do not implement move semantics (that is, do not overload their copy constructor and assignment operator with an rvalue reference version), the new swap behaves just like the old one.
22
Movability: facts! Remember: we are discussing C++ … things are not always clear and simple as you can/would expect std::move -> doesn’t move (is an unconditional cast) std::forward -> doesn’t forward (is a conditional cast) move is NOT always more cheap then copy! even if you explicit call std::move you can fall-back into a copy type&& doesn’t always represent an rvalue reference std::forward is not perfect! (not all types are correctly forwarded)
23
Resource Management: Smart Pointers
struct XMLNode {…} vector< XMLNode*> get_nodes(); void do_something (XMLNode*); … for (auto &node : get_node()) do_something (node); Why raw pointer are so bad? Is not clear who hold the resource Is not clear which is the exact type of the pointer Is not clear which function should be used to delete it (delete / delete [] ) Is difficult to avoid memory leak
24
Resource Management: Smart Pointers
struct XMLNode {…} vector< shared_ptr<XMLNode>> get_nodes(); void do_something (shared_ptr<XMLNode>); … for (auto &node : get_node()) do_something (node); To avoid this problem C++11 introduces: std::unique_ptr std::shared_ptr std::weak_ptr (not covered here) std::auto_ptr is deprecated!!!
25
Resource Management: shared_ptr
std::shared_ptr is the “augmented” version of unique_ptr. You can copy it and pass to your functions by value or by ref. Roughly we can see shared_ptr as pair of raw pointer and counter, when the counter goes to zero the “correct” destructor is invoked and the memory is released. void set_name(shared_ptr<XMLNode> node); … int main() { auto node = make_shared<XMLNode>(); //node.counter = 1 set_name(node, "body "); // node.counter = 2 } //node.counter = 0 invoke ~XMLNode() stackoverflow: C++ - passing references to std::shared_ptr or boost::shared_ptr (by Andrea Bigagli)
26
Resource Management: unique_ptr
std::unique_ptr embodies exclusive ownership semantics always owns what it points to. So copy a unique_ptr is not allowed but you can move it transferring the ownership. A common use of unique_ptr is a factory function (in general for managing resource with exclusive ownership semantics). unique_ptr<XMLNode> make_body() { auto node = make_unique<XMLNode>("body"); node->setAttribute("bgcolor", "#ABAB00"); return node; //implicit move } …. auto body= make_body(); // do smt with the body here } // destroy body C++14 make_unique is part of C++14 but probably your compiler has already implemented it
27
Lambda Expressions 1/3 [ <capture list> ] (<parameters>)
It’s a simplified notation for defining an anonymous function object It’s a shorthand to define a functor It’s something that generates a closure object [ <capture list> ] (<parameters>) mutable noexcept <return type> { <body> } See my talk: Lambdas Recipes (Italian C++ MeetUp 2014 Milano):
28
Lambda Expressions 2/3 [ <capture list> ] (<parameters>) mutable noexcept -> <return type> { <body> } Capture list: specify the name of local variables that are used in a lambdas (we can specify if they are taken by value, by ref or by move) Parameters: the list of parameters taken by lambdas (optional) An optional mutable: a useful way to change internal status of the lambdas An optional noexcept Return type: the type returned by lambdas (almost optional*) Body: the body of the lambdas (could be any kind of statements) * Optional in C++14. Optional in C++11 iff the lambdas is composed by one line.
29
What compiler roughly does!
Lambda Expressions 3/3 What we do [] (int a, int b) { return a + b; } What compiler roughly does! struct lambda0 { int operator() (int a, int b) const { return a + b; }
30
Lambdas in C++14 From C++14 new features are introduced:
We can use generic lambdas: [] (auto x, auto y ) { return x + y; } Initialized lambda capture We can use move in capture list: [ v = move (v) ] { /**/ } We can define and initialize new variable in capture list: [ s = "hello" ] { cout << s << endl; } * note the difference in const retention btw [c] or [=] (C++11) and [c=c] (C++14) captures Hint: until C++17 don’t use uniform initialization syntax inside capture list
31
Lambdas in STL (as predicate)
#include <algorithm> There are a lot of STL functions that accept a callable object and so even lambda: std::for_each std::count std::count_if std::find_if std::sort output vector<int> v{1, 2, 3, 4, 5}; for_each(v.cbegin(), v.cend(), [i = 0] (int n) mutable { cout << i++ << ") val: " << n << endl; }); 0) val: 1 1) val: 2 2) val: 3 3) val: 4 4) val: 5
32
Class Features Delegating Constructor Inheriting Constructors
In class member initializer Default & Delete Override & Final
33
Delegating constructor
class Widget { public: Widget() { init (0, 0); }; Widget(int pos_x, int pos_y) { init (pos_x, pos_y); } virtual void draw() {}; virtual void rotate(float a) {}; void init(int _x, int _y){}; private: int x, y; C++98 If I do not want to duplicate my code I’ve to define a generic (private) init function with an impact on performance See:
34
Delegating constructor
class Widget { public: Widget() : Widget(0, 0) {}; Widget(int pos_x, int pos_y) : x{pos_x}, y{pos_y} {} virtual void draw() {}; virtual void rotate(float a) {}; virtual ~Widget(){} private: int x, y; } C++11 But now we’ve got delegating const.!!! Instead of use a generic init function we can delegate the construction of our object to a different constructor Pay attention: when the delgating constructor concludes his job the object is considered “built & valid” so if the “parent constructor” throw the destructor will be invoked!
35
Inheriting constructor
class Widget { public: Widget() : Widget(0, 0) {}; Widget(int pos_x, int pos_y) {…} virtual void draw() {}; virtual void rotate(float a) {}; virtual ~Widget(){} private: int x, y; } class Button : public Widget { public: Button() : Widget(0, 0) {…}; Button (int pos_x, int pos_y) : Widget (pos_x, pos_y) {…} void draw() {}; void rotate(float a) {}; private: … } I’ve to overload base Constructor!
36
Inheriting constructor
class Widget { public: Widget() : Widget(0, 0) {}; Widget(int pos_x, int pos_y) {…} virtual void draw() {}; virtual void rotate(float a) {}; virtual ~Widget(){} private: int x, y; } class Button : public Widget { public: using Widget::Widget; void draw() {}; void rotate(float a) {}; private: … } C++11 More simple !!!
37
default & delete class Widget { public: Widget() : Widget(0, 0) {};
Widget(int pos_x, int pos_y) {…} Widget(const Widget& rs) = delete; virtual void draw() {}; virtual void rotate(float a) {}; virtual ~Widget() = default; private: int x, y; } In C++11 we can ask the compiler to generate or delete some special functions: constructors, destructor, copy assignment operators move assignment operators.
38
default & delete class Widget { public: Widget() : Widget(0, 0) {};
Widget(int pos_x, int pos_y) {…} Widget(const Widget& rs) = delete; virtual void draw() {}; virtual void rotate(float a) {}; virtual ~Widget() = default; private: int x, y; } Isn’t safe to copy an object via base class so disable Copy Constructor! (use a virtual clone function instead) Generate a public inline virtual destructor
39
but is not what we expect!
override & final void Widget::rotate(float a) { cout << "Widget::rotate" << endl; } class Button : public Widget { public: … virtual void draw() {} virtual void rotate(double a) { cout << "Button::rotate" << endl; C++98 Compile sure … but is not what we expect! { Button b; Widget& r = b; r.rotate(45.0f); } // output: Widget::rotate
40
override & final C++11 void Widget::rotate(float a) {
cout << "Widget::rotate" << endl; } class Button : public Widget { public: … virtual void draw() {} virtual void rotate(double a) override { cout << "Button::rotate" << endl; C++11 Now doesn’t compile!
41
error: overriding final function ‘virtual int Widget::generate_id()’
override & final struct GenIDPolicy { virtual int generate_id() { … } } class Widget : public GenIDPolicy { virtual int generate_id() final { … } … }; class Button : public Widget { public: virtual void draw() override {} virtual void rotate(float a) override {} int generate_id() { /* new policy */ } C++11 final instead is used to prevent overriding of a method of member base class. We can define an entire class as final. error: overriding final function ‘virtual int Widget::generate_id()’
42
Tuple & Tie Sol #1 class Student { public:
A classical design problem in C++ is: How I can return more than one value from my function? Consider this example: class Student { public: bool getCompleteName(srting& o_name, string& o_surname) const; … } Student s(…); string name, surname; s.getCompleteName(name, surname); Sol #1
43
Tuple & Tie Sol #2 C++11 class Student { public:
But since C++11 we’ve tuple & tie into the standard! std::tie permits us to easily unpack a tuple to its arguments or instances of std::ignore class Student { public: tuple<string, string> getCompleteName() const; … } Student s(...); // I’ve to define name & surname before to use tie string name, surname; tie(name, surname) = s.getCompleteName(); Sol #2 C++11
44
After several years C++ has got: Threads, Memory Model and Async Task.
During these years we’ve seen: pthread boost::thread CWinThread QThread … std::thread C++11
45
Threads: basics std::thread th ([]{
cout << "I’m a thread! " << endl; }); th.join(); void th_body(int n) { cout << "The answer is always: " << n; } std::thread th2 (th_body, 42); th2.detach(); We can define the body of the thread in place using lambdas In general we can use any callable object Note: thread’s constructor always copying arguments
46
Threads: an example // load data vector<unsigned int> v(10000);
We want to count how many prime numbers are present in a vector. We can use this simple serial algorithm: // load data vector<unsigned int> v(10000); // fill data with a sequence of positive number generate (v.begin(), v.end(), [n=0]() mutable {return n++;}); // then compute auto r = count_if (v.cbegin(), v.cend(), [](const auto& e){ return is_prime(e); }); cout << “Result: " << r << endl;
47
Threads: an example Or we can do in parallel! 1 2 3 4 … n
48
Threads: async We can simplify our code using std::async. This function create an “asynchronous” task and return a future to propagate the results of computation.
49
More Advanced Variadic Template: a template with support for an infinite list of parameters constexpr: indicates a value that it’s known during compilation noexcept(expr): a new attribute for a function that (essentially) say “this function doesn’t throw iff expr is true”
50
C++11: a concrete example
struct Point {int x, y;}; auto& f = Singleton<Point>::emplace(1, 5); auto& p = Singleton<Point>::getInstance(); cout << f.x << ", " << f.y << endl;
51
Do you remember our ZIP function?
Let me introduce the zip function. This function takes two list and pairs elements from the first list with the elements from the second list. zip :: [a] -> [b] -> [(a, b)] zip _ [] = [] zip [] _ = [] zip (x:xs) (y:ys) = (x, y) : zip xs ys Our goal is to implement it in C++11! Haskell Implementation ZIP 1 2 3 4 5 6 1, A 2, B 3, C A B C Thanks to lisperati.com
52
ZIP function in C++11 Now using C++14!
Haskell & other fun.lang. has tail call optimization, in C++ is not always true so: recursive -> iterative If possible prefer a std::algorithm to everything else!
53
What's next in C++17? Concept N4174, Call syntax: x.f(y) vs. f(x,y)
N4165 Unified Call Syntax D4128, Eric Nibler Range v3 lib. N4332, Networking library N3858, Resumable Functions N4230, nested namespace definitions like namespace A::B::C { } N3922, which fixes the most common pitfall with auto and {}, so that auto x{y}; Some cleanup! (auto_ptr, trigraph, bind1...) and much more… I hope to see more & more functional programming stuff in C++17 !!!
54
C++17: Which features would you like to be in?
Convincetemi ad usare il C++14 (Roberto Bettazzoni), C++ MeetUp Bologna 2014
55
Some books Tour of C++, Bjarne Stroustrup
The C++ Programming Language 4th edition, Bjarne Stroustrup Effective Modern C++, Scott Meyers The C++ Standard Library: A Tutorial and Reference (2nd), Nicolai M. Josuttis C++11 Rocks, Alex Korban
56
Some videos (in english)
Make Simple Tasks Simple, CPPCon Bjarne Stroustrup Back to the Basics Essentials of Modern C++ Style, CPPCon Herb Sutter An Effective C++11 & C++14, GoingNative Scott Meyers C++ Seasoning, GoingNative Sean Parent Effective C++, NDC Scott Meyers Type Deduction and Why You Care, CPPCon Scott Meyers (in italian) Il nuovo C++. Torniamo alle basi, Community Days 2014 – Marco Arena
57
Thanks!
58
About Me! Software Engineer @ Commprove (Firenze)
C++ (C++11/14), JavaScript, PHP5, HTML5/CSS3, Python, Java7 Haskell newbie Preferred OS: Linux especially Debian Linux Preferred PL: C++11/14 Preferred IDE: Sublime Text 3 & vim
Similar presentations
© 2025 SlidePlayer.com Inc.
All rights reserved.