Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

SEROM 2018 - 11/14/17/20 - C++ gestern heute und morgen

276 views

Published on

Die Programmiersprache C++ gehört immer noch zu den wichtigsten Programmiersprachen überhaupt. Gerade im Embedded Bereich vollzieht sich langsam die Abkehr von C zu C++ und ist dort alternativlos. Es hatte jedoch jahrelang den Anschein, als würde diese Sprache seit Jahren nicht weiterentwickelt und von den Features und Ausdrucksmöglichkeiten hinter neueren Sprachen zurückzufallen. In diesem Vortrag zeige ich an Codebeispielen, welche Revolution tatsächlich seit C++11 stattgefunden hat und dass die Sprache keinesfalls mehr mit der zu vergleichen ist, die man vielleicht vor Jahren kennen (und vielleicht hassen) gelernt hat. Die Umgestaltung der Sprache ist dabei keineswegs abgeschlossen sondern zeigt weitere, vielversprechende Konzepte am Horizont.

Published in: Software
  • Be the first to comment

  • Be the first to like this

SEROM 2018 - 11/14/17/20 - C++ gestern heute und morgen

  1. 1. 1 11/14/17/20 C++ gestern heute und morgen Prof. Dr. Herwig Henseler henseler@phwt.de http://www.herwig-henseler.de/phwt Twitter: @herwighenseler SEROM 3.0 – 19.10.2018 – Vechta
  2. 2. 2 C++ in den TOP 5 der uncoolsten Programmiersprachen?
  3. 3. 3 Tiobe Index Oktober 2018 Quelle: https://www.tiobe.com/tiobe-index/ # Sprache Rating 1 Java 17,8% 2 C 15,4% 3 C++ 7,6% 4 Python 7,1% 5 Visual Basic .NET 5,8% 6 C# 3,4% 7 PHP 2,7% 8 JavaScript 2,3%
  4. 4. 4Quelle: https://m.eet.com/media/1246048/2017-embedded-market-study.pdf
  5. 5. 5 Positive Eigenschaften Objekte auf Stack oder Heap Virtual nicht default Deterministische Speicherverwaltung Destruktoren Native OS-APIs konditionale Codegenerierung ... „You don‘t pay for things you don‘t need“
  6. 6. 6 Negative Eigenschaften 1 Buffer Overflows 2 Speicherlecks 3 Hängende Pointer 4 Dürftige Standardbibliothek 5 Verengende Konvertierung 6 int, bool, * zuweisungskompatibel 7 Kein Styleguide ...
  7. 7. 7 C++ 1.0 (1985) C++ 2.0 (1989) C++98 Erster Standard C++11 lambdas, type inference, typed enums, range-for, move- semantics, constexpr, regexp, smart pointer, array/vector, variadic templates, rvalue-references, static assignments, threads, initializer C++14 generic lambdas, locking, user defined literals C++17 parallel algorithms, map/reduce, tasks, optionals, variants, if-initializer, structured bindings C++20 concepts, coroutines, module system, reflection, transactional memory, networking, ranges, modules
  8. 8. 8 Compilerunterstützung C++11 gcc / clang++ in 2012 C++11 erst mit Visual Studio 2015 http://en.cppreference.com/w/cpp/compiler_support C++11 C++14 C++17 core library gcc 5.0 5.1 7.1 incomplete llvm/clang++ 3.8 3.8 5.0 incomplete msvc 2015.0 2017.0 2017.3 2017.3
  9. 9. 9 1 2 3 4 5 6 7 8 9 10 11 12 13 1 Buffer Overflows int carr[vmax]; int sum = 0; for (int i = 0; i <= vmax; ++i) { sum += carr[i]; } vector<int> vec(vmax); int sum{ 0 }; for (const auto x : vec) { sum += x; } int sum{ std::accumulate(begin(vec), end(vec), 0) }; C++98 C++11
  10. 10. 10 Summe von 250 Mio ints in [ms] Java: 122 ms Swift: 255 ms Ruby: 12 s Perl 16 s Python 35 s int carr[vmax]; for (size_t i = 0; i < vmax; ++i) { sum += carr[i]; } 66 ms vector<int> vec(vmax); for (const auto x : vec) { sum += x; } 68 ms for (size_t i = 0; i < vec.size(); ++i) { sum += vec.at(i); } 74 ms for (size_t i = 0; i < vec.size(); ++i) { sum += vec[i]; } 66 ms
  11. 11. 11 1 2 3 4 5 6 7 8 9 10 11 12 13 Geschwindigkeitsmessung #include <ctime> clock_t t1 = clock(); // zu testende Funktion ... clock_t t2 = clock(); int ms = t2 – t1; cout << ms; #include <chrono> auto t1 = std::chrono::high_resolution_clock::now(); // zu testende Funktion ... auto t2 = std::chrono::high_resolution_clock::now(); std::chrono::duration<double, std::milli> ms = t2 - t1; cout << ms.count(); C++98 C++11
  12. 12. 12 1 2 3 4 5 6 7 8 9 10 11 12 13 2 Speicherlecks // memory leak Kreis* kreis = new Kreis(300); kreis = 0; Kreis:Objekt Kreis:Objekt kreis kreis
  13. 13. 13 1 2 3 4 5 6 7 8 9 10 11 12 13 3 Hängende Zeiger // access violation Kreis* kreis1 = new Kreis(300); Kreis* kreis2 = kreis1; delete kreis1; kreis1 = 0; kreis2->setRadius(200); // crash (oder auch nicht!) Kreis:Objektkreis1 kreis2 kreis1 kreis2
  14. 14. 14 std::shared_ptr<> Zeiger auf T Zeiger auf control block T:Objekt reference count weak count control block std::shared_ptr<T> kreis
  15. 15. 15 1 2 3 4 5 6 7 8 9 10 11 12 13 „No naked new, no naked delete“ auto kreis1{ std::shared_ptr<Kreis>(new Kreis(300)) }; kreis2 = kreis1; kreis1 = nullptr; kreis2->setRadius(200); // Objekt noch da kreis2 = nullptr // reference count == 0 => delete auto kreis{ std::make_shared<Kreis>(300) }; C++11 C++14 Kreis:Objektkreis1 kreis2 1 0
  16. 16. 16 1 2 3 4 5 6 7 8 9 10 11 12 13 std::unique<> auto kreis1{ std::make_unique<Kreis>(300) }; auto kreis2 = kreis1; // verboten! kreis1 = nullptr; C++14 Keinerlei Geschwindigkeitsverlust zu „raw“ Zeigern!
  17. 17. 17 1 2 3 4 5 6 7 8 9 10 11 12 13 RAII void doSomethingWithMemoryLeak(void) { Kreis* kreis = new Kreis(300); if (kreis->getX() > 10) { throw; // delete kreis unterbleibt } delete kreis; } void doSomethingWithRAII(void) { const auto kreis{ std::make_unique<Kreis>(300) }; if (kreis->getX() > 10) { throw; } } RAII = Lebenszeit einer Ressource wird an die Lebenszeit einer lokalen Variablen gebunden. C++98 C++14
  18. 18. 18 4 Dürftige Standardbibliothek Bisher: C++ Ohne Bibliotheken/Frameworks kaum nutzbar  STL  Boost  Qt  Poco  ... Modernes C++ übernimmt viel davon in std::  Problem: Frameworks müssen nachziehen
  19. 19. 19 5 Verengende Konvertierung „modernere“ Schreibweise int x = 0; // normale Syntax int x(0); // „OOP“-Syntax int x{ 0 }; // C++11: Syntax über Initialisierer Initializer verhindern narrowing conversion int pi = 3.14; // implizite Typkonvertierung: x hat Wert 3 int pi{ 3.14 }; // compilerfehler
  20. 20. 20 1 2 3 4 5 6 7 8 9 10 11 12 13 6 NULL zuweisungskompatibel zu Zeigern Person* p1 = 0; Person* p2 = NULL; Person* p3 = nullptr; int i1 = 0; int i2 = NULL; int i3 = nullptr; // Compilerfehler C++98 C++11
  21. 21. 21 1 2 3 4 5 6 7 8 9 10 11 12 13 6 int zuweisungskompatibel zu bool bool b = 0; if (i = 42) { ... } // Tippfehler, gewollt war i == 42 if (42 = i) { ... } // "Lösung": yoda-condition
  22. 22. 22 7 Kein Styleguide C++ Core Guidelines (>500 Seiten) AUTOSAR „Guidelines for the use of the C++14 language in critical and safety-related systems“ (371 Seiten) SEI CERT C++ Coding Standard: Rules for Developing Safe, Reliable, and Secure Systems in C++ (430 Seiten)
  23. 23. 23 1 2 3 4 5 6 7 8 9 10 11 12 13 C++11 constexpr class Point { public: constexpr Point(const int x, const int y) : _x(x), _y(y) {} constexpr int getX(void) const { return _x; } private: int _x, _y; }; int main(void) { constexpr Point points[] = { Point(10, 20), Point(30, 40) }; constexpr int x1{ points[1].getX() }; // 30 zur compiletime!
  24. 24. 24 1 2 3 4 5 6 7 8 9 10 11 12 13 C++11 Lambdas vector<int>::iterator i = v.begin(); for (; i != v.end(); ++i) { if (*i > x && *i < y) break; } auto i{ std::find_if(begin(v), end(v), [=](int i){ return i > x && i < y; }) }; C++98 C++11
  25. 25. 25 1 2 3 4 5 6 7 8 9 10 11 12 13 C++11 Benutzerdefinierte Literale auto distance = 1.0_km + 2.0_m + 3.0_cm; cout << distance << " meter"; // Ausgabe: // 1002.03 meter
  26. 26. 26 1 2 3 4 5 6 7 8 9 10 11 12 13 clang-tidy linter $ clang-tidy --list-checks -checks='*' | grep "modernize" modernize-avoid-bind modernize-deprecated-headers modernize-loop-convert modernize-make-shared modernize-make-unique modernize-pass-by-value modernize-raw-string-literal modernize-redundant-void-arg modernize-use-default modernize-replace-auto-ptr modernize-use-emplace modernize-shrink-to-fit modernize-use-nullptr modernize-use-auto modernize-use-override modernize-use-bool-literals modernize-use-using
  27. 27. 27 1 2 3 4 5 6 7 8 9 10 11 12 13 C++17 Optionals std::optional<string> create(bool b) { if (b) { return "Hallo, Welt!"; } return {}; } int main(void) { cout << create(false).value_or("empty") << endl; if (auto str = create(true)) { cout << *str << 'n'; }
  28. 28. 28 1 2 3 4 5 6 7 8 9 10 11 12 13 C++17 Trailing return, mehrere Rückgabewerte, if mit Initialisierer auto find(void) -> std::tuple<int, string, double> { return std::make_tuple(42, "fortytwo", 42.0); } int main(void) { if (auto [id, name, score] = find(); score > 17) { cout << score << endl; } // id, name, score nicht mehr gültig
  29. 29. 29 1 2 3 4 5 6 7 8 9 10 11 12 13 C++20 Contracts int gcd(int a, int b) { [[ expects: a > 0 ]] // Prüfe Vorbedingungen [[ expects: b > 0 ]] while (b != 0) { const int c = a % b; a = b; b = c; } [[ ensures: a > 0 ]] // Prüfe Nachbedingungen return a; }
  30. 30. 30 Jenseits von C++20 Neues Modulsystem (ohne .h/.cpp)! Coroutinen Transactional memory Reflection Metaklassen
  31. 31. 31
  32. 32. 32 Kern wird vorsichtig erweitert Bibliotheken ergänzen moderne Konzepte C++ ist eine hochkomplexe Sprache (geworden)!
  33. 33. 33 „Writing software using C++98 in 2018 is an anti-pattern“
  34. 34. 34 C++ 1.0 (1985) C++ 2.0 (1989) C++98 Erster Standard C++11 lambdas, type inference, typed enums, range-for, move- semantics, constexpr, regexp, smart pointer, array/vector, variadic templates, rvalue-references, static assignments, threads, initializer C++14 generic lambdas, locking, user defined literals C++17 parallel algorithms, map/reduce, tasks, optionals, variants, if-initializer, structured bindings C++20 concepts, coroutines, module system, reflection, transactional memory, networking, ranges, modules
  35. 35. 35
  36. 36. 36 [](){}(); Lösung: Ein leeres Lambda, welches sofort aufgerufen wird.
  37. 37. 37 Ein Rätsel Was liefert keine Variable i vom Typ int mit dem Wert 2? 1) int i = 2; 2) int i = { 2 }; 3) int i{ 2 }; 4) int i(2); 5) auto i = 2; 6) auto i = { 2 }; 7) auto i{ 2 }; 8) auto i(2); Lösung: 6 und 7 liefern eine std::initializer_list<int>

×