Writing Modern C++ Marc Grégoire Software Architect April 3 rd 2012.

Slides:



Advertisements
Similar presentations
Chapter 17 vector and Free Store Bjarne Stroustrup
Advertisements

Dynamic Memory Allocation in C.  What is Memory What is Memory  Memory Allocation in C Memory Allocation in C  Difference b\w static memory allocation.
Chapter 18 Vectors and Arrays John Keyser’s Modification of Slides by Bjarne Stroustrup
What's new in Microsoft Visual C Preview
Dynamic Memory Management
Writing “Exception Safe” C++ Alan Griffiths –Work: Experian Limited Senior Systems Consultant Mentoring & development OOA/OOD/C++
Chapter 17 vector and Free Store John Keyser’s Modifications of Slides By Bjarne Stroustrup
Chapter 8 Scope, Lifetime and More on Functions. Definitions Scope –The region of program code where it is legal to reference (use) an identifier Three.
Portability and Safety Mahdi Milani Fard Dec, 2006 Java.
Dynamic Allocation Eric Roberts CS 106B February 4, 2013.
CSE 332: C++ memory management idioms C++ Memory Management Idioms Idioms are reusable design techniques in a language –We’ll look at 4 important ones.
Memory allocation CSE 2451 Matt Boggus. sizeof The sizeof unary operator will return the number of bytes reserved for a variable or data type. Determine:
CSE 332: C++ copy control I Copy Control (Part I) Copy control consists of 5 distinct operations –A copy constructor initializes an object by duplicating.
1 Objects and ClassesStefan Kluth 1.6Objects and Classes 1.6What is an Object? 1.7Objects and Classes 1.8Object Interface, Class Inheritance, Polymorphism.
George Blank University Lecturer. CS 602 Java and the Web Object Oriented Software Development Using Java Chapter 4.
CIS 101: Computer Programming and Problem Solving Lecture 8 Usman Roshan Department of Computer Science NJIT.
Software Testing and Quality Assurance
Rossella Lau Lecture 8, DCO10105, Semester B, DCO10105 Object-Oriented Programming and Design  Lecture 8: Polymorphism & C++ pointer  Inheritance.
C#.NET C# language. C# A modern, general-purpose object-oriented language Part of the.NET family of languages ECMA standard Based on C and C++
Pointers and Dynamic Variables. Objectives on completion of this topic, students should be able to: Correctly allocate data dynamically * Use the new.
1 ES 314 Advanced Programming Lec 3 Sept 8 Goals: complete discussion of pointers discuss 1-d array examples Selection sorting Insertion sorting 2-d arrays.
Review on pointers and dynamic objects. Memory Management  Static Memory Allocation  Memory is allocated at compiling time  Dynamic Memory  Memory.
CS-2303 System Programming Concepts
1 Procedural Concept The main program coordinates calls to procedures and hands over appropriate data as parameters.
C++ for Java Programmers Chapter 1 Basic Philosophical Differences.
A Moderately Directed Rant.  It’s very likely that you’ve been writing totally incorrect code without realizing it  Once you do realize it, it’s usually.
EE4E. C++ Programming Lecture 1 From C to C++. Contents Introduction Introduction Variables Variables Pointers and references Pointers and references.
Chapter 5: Programming Languages and Constructs by Ravi Sethi Activation Records Dolores Zage.
CS 11 java track: lecture 1 Administrivia need a CS cluster account cgi-bin/sysadmin/account_request.cgi need to know UNIX
CSE 425: Object-Oriented Programming I Object-Oriented Programming A design method as well as a programming paradigm –For example, CRC cards, noun-verb.
Computer Science and Software Engineering University of Wisconsin - Platteville 2. Pointer Yan Shi CS/SE2630 Lecture Notes.
Optimizing C++ Applications Scott MacHaffie Schrödinger, Inc. 1 / 18.
Chapter 25: Code-Tuning Strategies. Chapter 25  Code tuning is one way of improving a program’s performance, You can often find other ways to improve.
1 C++ Classes and Data Structures Jeffrey S. Childs Chapter 5 An Array Class Jeffrey S. Childs Clarion University of PA © 2008, Prentice Hall.
Pointers OVERVIEW.
Nirmalya Roy School of Electrical Engineering and Computer Science Washington State University Cpt S 223 – Advanced Data Structures C++ Review Part-I.
C++ Memory Overview 4 major memory segments Key differences from Java
1 C++ Classes and Data Structures Jeffrey S. Childs Chapter 4 Pointers and Dynamic Arrays Jeffrey S. Childs Clarion University of PA © 2008, Prentice Hall.
Pointers and Dynamic Memory Allocation Copyright Kip Irvine 2003, all rights reserved. Revised 10/28/2003.
CPSC 252 Dynamic Memory Allocation Page 1 Dynamic memory allocation Our first IntVector class has some serious limitations the capacity is fixed at MAX_SIZE.
 Managing the heap  Resource acquisition is initialization (RAII)  Overriding operator new and delete  Class-based memory pools.
Dynamic Memory Allocation. Domain A subset of the total domain name space. A domain represents a level of the hierarchy in the Domain Name Space, and.
Object-Oriented Programming in C++
Lecture 3 Classes, Structs, Enums Passing by reference and value Arrays.
Functions Illustration of: Pass by value, reference Scope Allocation Reference: See your CS115/215 textbook.
C++ 程序语言设计 Chapter 12: Dynamic Object Creation. Outline  Object creation process  Overloading new & delete.
1 Classes II Chapter 7 2 Introduction Continued study of –classes –data abstraction Prepare for operator overloading in next chapter Work with strings.
Herb Sutter.  What  What makes “C++11 feel like a new language”  Why  Values and tenets for language design  Contrast between native C++ and managed.
Engineering Classes. Objectives At the conclusion of this lesson, students should be able to: Explain why it is important to correctly manage dynamically.
Java & C++ Comparisons How important are classes and objects?? What mechanisms exist for input and output?? Are references and pointers the same thing??
1 Chapter 15-1 Pointers, Dynamic Data, and Reference Types Dale/Weems.
Reference Types CSE301 University of Sunderland Harry R Erwin, PhD.
CHAPTER 18 C – C++ Section 1: Exceptions. Error Handling with Exceptions Forces you to defend yourself Separates error handling code from the source.
Pointers and References. Pointers & Memory 0x000x040x080x0B0x100x140x180x1B0x20.
CSE 332: C++ Exceptions Motivation for C++ Exceptions Void Number:: operator/= (const double denom) { if (denom == 0.0) { // what to do here? } m_value.
SEG4110 – Advanced Software Design and Reengineering TOPIC I Introduction to C++ For those who know Java And OO Principles in General.
CO4301 – Advanced Games Development Week 1 Introduction
Memory Management.
Pointers Revisited What is variable address, name, value?
void Pointers Lesson xx
Dynamic Memory Allocation
Object Oriented Programming COP3330 / CGS5409
understanding memory usage by a c++ program
Chapter 15 Pointers, Dynamic Data, and Reference Types
Overview of Memory Layout in C++
Binding Times Binding is an association between two things Examples:
Destructor CSCE 121 J. Michael Moore.
Destructor CSCE 121.
Dynamic Memory.
Workshop 1++: A bit of C++
Presentation transcript:

Writing Modern C++ Marc Grégoire Software Architect April 3 rd 2012

Agenda  Why C++?  C++ Core Value  Modern C++  Resources

Why C++?  C++ is having a kind of renaissance  People are coming back to C++  Main reason: performance / €  You want to use the hardware as efficient as possible and squeeze the most out of it  Mobile devices: have limited power, use it efficiently  Datacenters: reducing power requirements directly results in saving money

C++ Core Value  Efficient abstraction  Strong abstraction: Type-safe OO and templates for powerful modeling, without sacrificing control and efficiency  Full control over code execution and memory: you can always express what you want to do you can always control memory and data layout exactly, if you want to  Pay-as-you go efficiency no mandatory overheads, don’t pay for what you don’t use Example: just because C++ supports virtual functions, you don’t pay a penalty for their support if you don’t use them

C++ Core Value  Cross platform, cross compiler, cross operating system  Performance very important “It’s incredibly important for C++ to be the language of performance. If there is a language lower than C++ and that has more performance, we didn’t do our job as a C++ community.” – Herb Sutter

C++ Core Value “The going word at Facebook is that ‘ reasonably written C++ code just runs fast,’ which underscores the enormous effort spent at optimizing PHP and Java code. Paradoxically, C++ code is more difficult to write than in other languages, but efficient code is a lot easier.” – Andrei Alexandrescu

Modern C++  Clean, Safe, Fast  Things to unlearn  Lambda expressions  Old C++ versus new C++  Avoid delete  Automatic lifetime (stack & heap)  Containers  Loops  Algorithms  Move semantics  Compile time encapsulation

Clean, Safe, Fast  Modern C++ code can be Clean, Safe, and Fast  Clean: express with minimal lines of code what you want to do, just as in other modern languages, resulting in easy to read and easy to understand code  Safe: modern C++ code is exception safe, memory safe, …  Fast: because it’s C++

Modern C++  Clean, Safe, Fast  Things to unlearn  Lambda expressions  Old C++ versus new C++  Avoid delete  Automatic lifetime (stack & heap)  Containers  Loops  Algorithms  Move semantics  Compile time encapsulation

Things to Unlearn  If you have used C++ before, you might have to unlearn a couple of things  Avoid low-level pointer manipulation and raw memory manipulation, in favor of higher level constructs  Do not use delete / delete [], use smart pointer; it’s:  Exceptions safe  Leak free  Deterministic, unlike garbage collectors

Things to Unlearn  Never do something like: FILE* f = fopen("data.ext", "w"); //... fclose(f);  Not exception safe!  Use RAII (Resource Acquisition Is Initialization)  Write a wrapper class: Constructor  opens the file Destructor  automatically closes the file  Often you can use std::shared_ptr, even for the above example Deterministic

Things to Unlearn  Instead of: FILE* f = fopen("data.ext", "w"); //... fclose(f);  Use: shared_ptr filePtr(fopen("data.ext", "w"), fclose);  Or write your own wrapper

Things to Unlearn  Avoid the old C-style algorithms, instead, use modern C++ algorithms

Things to Unlearn  For example, qsort() is a C-style algorithm with following signature: void qsort (void *base, size_t num, size_t size, int (*comparator) (const void *, const void *)); // Call it as follows for a double array qsort(myDoubleArray, n, sizeof(double), compare_double); Memory to be sorted Number of elements in memory Number of bytes in one element Comparison function to compare two elements

Things to Unlearn Use C++ algorithms like std::sort() Example: std::sort(begin(vec), end(vec)); Side-note: Even though std::sort() is a higher level construct, it’s faster than qsort by a large factor (not just a few percent)

Modern C++  Clean, Safe, Fast  Things to unlearn  Lambda expressions  Old C++ versus new C++  Avoid delete  Automatic lifetime (stack & heap)  Containers  Loops  Algorithms  Move semantics  Compile time encapsulation

Lambda Expressions  Syntax [capture_block](parameters) mutable exception_specification -> return_type { body }  capture block: how to capture variables from enclosing scope  parameters (optional): parameter list, just like a function  mutable (optional): variables captured by-value are const, mutable makes them non-const  exception_specification (optional): = throw list  return_type (optional): the return type; if omitted If the body of the lambda expression is of the following form: { return expression; } the type of expression will become the return_type of the lambda expression. Otherwise the return_type is void

Lambda Expressions  Basic example: int main() { []{cout << "Hello from Lambda" << endl;}(); }  Capture block  [ ] captures nothing  [=] captures all variables by value  [&] captures all variables by reference  [&x] captures only x by reference and nothing else  [x] captures only x by value and nothing else  [=, &x, &y] captures by value by default, except variables x and y, which are captured by reference  [&, x] captures by reference by default, except variable x, which is captured by value

Modern C++  Clean, Safe, Fast  Things to unlearn  Lambda expressions  Old C++ versus new C++  Avoid delete  Automatic lifetime (stack & heap)  Containers  Loops  Algorithms  Move semantics  Compile time encapsulation

Old C++ Versus New C++ Old circle* p = new circle(42); vector vw = load_shapes(); for (vector ::iterator i = vw.begin(); i != vw.end(); ++i) { if (*i && **i == *p) cout << **i << " is a match\n"; } for (vector ::iterator i = vw.begin(); i != vw.end(); ++i) { delete *i; } delete p; New auto p = make_shared (42); vector > vw = load_shapes(); for_each (begin(vw), end(vw), [&](shared_ptr & s) { if (s && *s == *p) cout << *s << " is a match\n"; } ); T*  shared_ptr new  make_shared no need for “delete” automatic lifetime management exception-safe for/while/do  std:: algorithms [&] lambda functions auto type deduction not exception-safe missing try/catch, __try/__finally

Modern C++  Clean, Safe, Fast  Things to unlearn  Lambda expressions  Old C++ versus new C++  Avoid delete  Automatic lifetime (stack & heap)  Containers  Loops  Algorithms  Move semantics  Compile time encapsulation

Avoid Delete  Write your code in such a way that there is never a need to use delete or delete[]

Avoid Delete  Don’t write code as follows: void foo() { MyObject* p = new MyObject(); //... delete p; }  It’s not exception safe!

Avoid Delete  Instead use shared_ptr or unique_ptr: void foo() { unique_ptr p = new MyObject(); //... }  Or, even better, just do: void foo() { MyObject obj; //... }

Modern C++  Clean, Safe, Fast  Things to unlearn  Lambda expressions  Old C++ versus new C++  Avoid delete  Automatic lifetime (stack & heap)  Containers  Loops  Algorithms  Move semantics  Compile time encapsulation

Automatic Lifetime  Automatic Lifetime = Efficient + Exception Safe class widget { private: gadget g; public: void draw(); }; void f() { widget w; /*... */ w.draw(); /*... */ } lifetime automatically tied to enclosing object no leak, exception safe lifetime automatically tied to enclosing scope constructs w, including the w.g gadget member Automatic destruction and deallocation for w and w.g Automatic exception safety, as if “finally { w.g.dispose(); w.dispose(); }”

The Heap and Smart Pointers class gadget; class widget { private: shared_ptr g; }; class gadget { private: weak_ptr w; }; shared ownership keeps gadget alive w/auto lifetime mgmt no leak, exception safe use weak_ptr to break reference-count cycles Side-note: Never use the old auto_ptr, it’s officially deprecated!

The Heap and Smart Pointers class node { vector > children; node* parent; /* … */ public: node( node* parent_) : parent(parent_) { children.push_back( new node(…) ); /* … */ } }; unique ownership node owns its children no leak, exception safe node observes its parent plain “new” should immediately initialize another object that owns it, example unique_ptr or shared_ptr

C++ and Garbage Collection “C++ is the best language for garbage collection principally because it creates less garbage.” — Bjarne Stroustrup

Modern C++  Clean, Safe, Fast  Things to unlearn  Lambda expressions  Old C++ versus new C++  Avoid delete  Automatic lifetime (stack & heap)  Containers  Loops  Algorithms  Move semantics  Compile time encapsulation

Containers  Avoid using C-style arrays  Instead use modern constructs such as STL containers  std::vector  std::array  std::map  std::unordered_map  std::multimap  std::unordered_multimap  std::set  std::unordered_set  std::multiset  std::unordered_multiset  std::list  std::forward_list Your default container: vector compact, efficient: cache- friendly, prefetcher-friendly fixed size vector Key-value-pairs: map (tree) or unordered_map (hash) set: Like map, but only keys

Containers - Examples vector v; v.push_back("Geddy Lee"); array a; a[0] = 123; map phone; phone["Alex Lifeson"] = "+1 (416) "; multimap phone; phone["Neil Peart"] = "+1 (416) "; phone["Neil Peart"] = "+1 (905) "; unordered_map phone; phone["Alex Lifeson"] = "+1 (416) "; unordered_multimap phone; phone["Neil Peart"] = "+1 (416) "; phone["Neil Peart"] = "+1 (905) ";

Modern C++  Clean, Safe, Fast  Things to unlearn  Lambda expressions  Old C++ versus new C++  Avoid delete  Automatic lifetime (stack & heap)  Containers  Loops  Algorithms  Move semantics  Compile time encapsulation

Loops Old for (auto i = v.begin(); i != v.end(); ++i) { /*... */ } auto i = v.begin(); for (; i != v.end(); ++i) { if (*i > x && *i < y) break; } New for_each (begin(v), end(v), [](string& s) { /*... */ } ); auto i = find_if(begin(v), end(v), [=](int i) { return i > x && i < y; } ); for/while/do  std:: algorithms [&] lambda functions for_each to visit each element find_if to find a match prefer non-member begin()/end() arbitrary length lambda bodies, just put the loop body inside the lambda

Modern C++  Clean, Safe, Fast  Things to unlearn  Lambda expressions  Old C++ versus new C++  Avoid delete  Automatic lifetime (stack & heap)  Containers  Loops  Algorithms  Move semantics  Compile time encapsulation

Algorithms  Don’t write your own algorithms unless you have a good reason or there is no standard algorithm for your use-case  Prefer standard algorithms  for_each(): Your default traversal algorithm transform() for not-in-place semantics  find_if(): Your default search algorithm  sort(), lower_bound(), …: Your default sorting and searching

Algorithms  Utility Algorithms  min(), max(), minmax(), swap()  minmax() example (C++11) int x1 = 2, x2 = 9, x3 = 3, x4 = 12; pair p1 = minmax({x1,x2,x3,x4}); cout << "Minmax of 4 elements is " << p1.first << "," << p1.second << endl;

Algorithms  Nonmodifying algorithms  Search algorithms find(), find_if(), find_if_not(), find_first_of(), search_n(), lower_bound(), upper_bound(), equal_range(), minmax_element(), all_of(), any_of(), none_of(), …  Numerical processing algorithms count(), count_if(), accumulate(), inner_product(), …  Comparison algorithms equal(), mismatch(), …  Operational algorithms for_each()

Algorithms  Nonmodifying algorithms examples  // Find min and max with 1 algorithm auto minmax = minmax_element(begin(vec), end(vec)); cout << "Min = " << *(minmax.first) << " and Max = " << *(minmax.second) << endl;  // Find the first subsequence of two consecutive 8s auto it = search_n(begin(vec), end(vec), 2, 8);  // all_of() vector vec = {1,1,1,1}; bool b = all_of(begin(vec), end(vec), [](int i){return i == 1;});

Algorithms  Numerical processing algorithms examples  // Calculate arithmetic mean of the elements in a vector double sum = accumulate(begin(vec), end(vec), 0); double avg = sum / vec.size();  // Calculate geometric mean of the elements in a vector double mult = accumulate(begin(vec), end(vec), 1, [](int num1, int num2){return num1 * num2;}); double geomean = pow(mult, 1.0 / vec.size());  // Create a vector with values vector vec(10); iota(begin(vec), end(vec), 5);

Algorithms  Modifying algorithms  transform(), copy(), copy_if(), move(), swap_ranges(), replace(), replace_if(), fill(), generate(), remove(), remove_if(), reverse(), rotate(), next_permutation(), …

Algorithms  Modifying algorithms examples  // Add 100 to each element in the vector transform(begin(vec), end(vec), begin(vec), [](int i){return i + 100;});  // Replace all values < 0 with 0 replace_if(begin(vec), end(vec), [](int i){return i < 0;}, 0);  // Remove all empty strings from a vector of strings // (Use remove-erase pattern!) auto it = remove_if(begin(strings), end(strings), [](const string& str){return str.empty();}); // erase the removed elements strings.erase(it, strings.end());

Algorithms  Sorting algorithms  sort(), stable_sort(), partial_sort(), merge(), …  Set algorithms  set_union(), set_intersection(), set_difference(), set_symmetric_difference(), …

Algorithms  Sorting algorithms example  If you want to do some binary search (lower_bound, upper_bound, equal_range, …), the sequence should be sorted first  Be sure to sort the sequence with the same predicate as you give to the search algorithm  Use named lambda, example: auto comp = [](const widget& w1, const widget& w2) { return w1.weight() < w2.weight(); } sort(begin(v), end(v), comp); auto i = lower_bound(begin(v), end(v), w, comp);

Modern C++  Clean, Safe, Fast  Things to unlearn  Lambda expressions  Old C++ versus new C++  Avoid delete  Automatic lifetime (stack & heap)  Containers  Loops  Algorithms  Move semantics  Compile time encapsulation

Move Semantics  C++11 Move Semantics increases efficiency and results in cleaner, easier to understand code  Why is move semantics useful?

Move Semantics – Why useful? set load_huge_data() { set ret; // … load data and populate ret … return ret; } widgets = load_huge_data(); vector v = AMillionStrings(); v.insert(begin(v)+v.size()/2, "tom"); v.insert(begin(v)+v.size()/2, "richard"); v.insert(begin(v)+v.size()/2, "harry"); HugeMatrix operator+( const HugeMatrix&, const HugeMatrix& ); hm3 = hm1+hm2; efficient, no deep copy no need for “heap allocation + return a pointer” workaround efficient, no deep copy-shuffle (just 1.5M ptr/len assignments) efficient, no extra copies

Move Semantics – How To Implement? class my_class { unique_ptr data; public: /*... */ my_class(my_class&& other) : data(move(other.data)) { } my_class& operator=(my_class&& other) { data = move(other.data); } void method() { if (!data) throw "moved-from object"; } }; check (if appropriate)  Needs:  Move constructor  Move assignment operator

Move Semantics – When?  If you have a copy constructor or copy assignment operator: Also implement move versions if they can be cheaper than a deep copy  Some types have only move versions, and no copy versions  For example: some types are naturally move-only, such as unique_ptr

Modern C++  Clean, Safe, Fast  Things to unlearn  Lambda expressions  Old C++ versus new C++  Avoid delete  Automatic lifetime (stack & heap)  Containers  Loops  Algorithms  Move semantics  Compile time encapsulation

Compile Time Encapsulation?  Use the Pimpl idiom to truly hide private members class my_class { //... all public and protected stuff goes here... private: class impl; unique_ptr pimpl;// opaque type here }; class my_class::impl {// defined privately here //... all private data and functions: all of these // can now change without recompiling callers... }; my_class::my_class() : pimpl(new impl) { /*... set impl values... */ }  Avoids rebuild cascades  Most appropriate for types used often my_class.h my_class.cpp

Resources  “Writing modern C++ code: how C++ has evolved over the years” – Herb Sutter   “GoingNative 2012, Keynote: C++ Style” – Bjarne Stroustrup  Bjarne-Stroustrup-Cpp11-Style Bjarne-Stroustrup-Cpp11-Style  Presentations from GoingNative 2012   Professional C++, 2 nd Edition 

Questions ? ? I would like to thank Herb Sutter from Microsoft for his permission to base this presentation on one that he wrote for Build 2011.

Widescreen Test Pattern (16:9) Aspect Ratio Test (Should appear circular) 16x9 4x3