diff --git a/c++.html.markdown b/c++.html.markdown index fc9f6ce2..176ea1a8 100644 --- a/c++.html.markdown +++ b/c++.html.markdown @@ -72,7 +72,7 @@ void func(); // function which may accept any number of arguments int* ip = nullptr; // C standard headers are available in C++. -// C headers end in .h, while +// C headers end in .h, while // C++ headers are prefixed with "c" and have no ".h" suffix. // The C++ standard version: @@ -761,7 +761,7 @@ failure: // things are a little cleaner, but still sub-optimal. void doSomethingWithAFile(const char* filename) { - FILE* fh = fopen(filename, "r"); // Open the file in read mode + FILE* fh = fopen(filename, "r"); // Open the file in shared_ptrread mode if (fh == nullptr) throw std::runtime_error("Could not open the file."); @@ -814,6 +814,57 @@ void doSomethingWithAFile(const std::string& filename) // - Mutexes using lock_guard and unique_lock +///////////////////// +// Smart Pointer +///////////////////// + +// Generally a smart pointer is a class, which wraps a "raw pointer" (usage of "new" +// respectively malloc/calloc in C). The goal is to be able to +// manage the lifetime of the object being point to without explicitly deleting +// the object. The term itself simply describes a set of pointers with the +// mentioned abstraction. +// Basically smart pointers should preferred over raw pointers, to prevent +// risky memory leaks, which happens if you forget to delete the object. + +// Usage of a raw pointer: +Dog* ptr = new Dog(); +ptr->bark(); +delete ptr; + +// With the usage of smart pointers you dont have to worry about the deletion +// of a object anymore. +// A smart pointer describes a policy, to count the references on the +// pointer. As matter of fact the objects gets destroyed when the last +// reference on the object gets destroyed. + +// Usage of "std::shared_ptr": +void foo() +{ +// Its not longer necessary to delete the Dog. +std::shared_ptr doggo(new Dog()); +doggo->bark(); +} + +// Beware of possible circular references!!! +// There will be always a reference, so it will be never destroyed! +std::shared_ptr doggo_one (new Dog()); +std::shared_ptr doggo_two (new Dog()); +doggo_one = doggo_two; // p1 references p2 +doggo_two = doggo_one; // p2 references p1 + +// As mentioned before there is a set of smart pointers. The way you have to +// use it, is always the same. +// This leads us to question, when to use which one? +// std::unique_ptr - use it when you just want to hold one reference on +// the same object. +// std::shared_ptr - use it when you want to hold multiple references on the +// same object and want to make sure that it´s de-allocated +// when all refences are gone. +// std::weak_ptr - use it when you want to hold multiple references from +// different places for references for which it´s no problem +// tp de-allocate. + + ///////////////////// // Containers ///////////////////// @@ -877,7 +928,7 @@ cout << ST.size(); // will print the size of set ST // Output: 0 // NOTE: for duplicate elements we can use multiset -// NOTE: For hash sets, use unordered_set. They are more efficient but +// NOTE: For hash sets, use unordered_set. They are more efficient but // do not preserve order. unordered_set is available since C++11 // Map @@ -906,7 +957,7 @@ cout << it->second; // Output: 26 -// NOTE: For hash maps, use unordered_map. They are more efficient but do +// NOTE: For hash maps, use unordered_map. They are more efficient but do // not preserve order. unordered_map is available since C++11. // Containers with object keys of non-primitive values (custom classes) require diff --git a/de-de/c++-de.html.markdown b/de-de/c++-de.html.markdown index eec11d61..cef7514b 100644 --- a/de-de/c++-de.html.markdown +++ b/de-de/c++-de.html.markdown @@ -23,9 +23,11 @@ entworfen wurde um, - generische Programmierung zu unterstützen Durch seinen Syntax kann sie durchaus schwieriger und komplexer als neuere Sprachen sein. -Sie ist weit verbeitet, weil sie in Maschinen-Code compiliert, welches direkt vom Prozessor ausgeführt + +Sie ist weit verbreitet, weil sie in Maschinen-Code kompiliert, welches direkt vom Prozessor ausgeführt werden kann und somit eine strikte Kontrolle über die Hardware bietet und gleichzeitig -High-Level-Features wie generics, exceptions und Klassen enthält. (wie C) +High-Level-Features wie generics, exceptions und Klassen enthält. + Diese Kombination aus Geschwindigkeit und Funktionalität bildet C++ und ist eine der weitverbreitesten Programmiersprachen. @@ -34,19 +36,20 @@ weitverbreitesten Programmiersprachen. // Vergleich zu C ////////////////// -// C++ ist fast eine Untermenge von C and teilt sich grundsätzlich den -// Syntax für Variablen Deklarationen, primitiven Typen und Funktionen. +// C ist fast eine Untermenge von C++ und teilt sich grundsätzlich den +// Syntax für Variablen Deklarationen, primitiven Typen und Funktionen. // Wie in C ist der Programmeinsprungpunkt eine Funktion, welche "main" genannt wird und -// einen Ineteger als Rückgabetyp besitzt. +// einen Integer als Rückgabetyp besitzt. + // Dieser Wert fungiert als Beendigungsstatus des Programms. // Siehe: https://de.wikipedia.org/wiki/Return_Code für weitere Informationen int main(int argc, char** argv) { // Kommandozeilen Argumente werden genauso wie in C über argc und argv übergeben - // argc entspricht der Anzahl von Argumenten und argv ist ein Array von C-style + // argc entspricht der Anzahl von Argumenten und argv ist ein Array von C-style // strings (char*), welche die Argumente repräsentieren. - // Das erste Argument ist der Name des Programms welches aufgerufen wird. + // Das erste Argument ist der Name des Programms, welches aufgerufen wird. // Argc und argv können, wenn nicht benötigt, weg gelassen werden, indem // die Funktionssignatur "int main()" verwendet wird. @@ -54,12 +57,12 @@ int main(int argc, char** argv) return 0; } -// C++ unterscheidet sich in einigen Punkten: +// C++ unterscheidet sich in einigen Punkten von C: -// In C++ sind Zeichen-Literale chars +// In C++ sind Zeichen-Literale char´s sizeof('c') == sizeof(char) == 1 -// In C sind Zeichen-Literale ints +// In C sind Zeichen-Literale int´s sizeof('c') == sizeof(int) // C++ verwendet striktes prototyping @@ -71,8 +74,8 @@ void func(); // Funktion mit beliebiger Anzahl von Argumenten // Verwende nullptr, anstatt von NULL!!! int* ip = nullptr; -// C standard headers sind in C++ verfügbar. -// C header enden mit .h, während +// C standard header sind in C++ verfügbar. +// C header enden mit .h, während // C++ header das Präfix "c" besitzen und kein ".h" Suffix verwenden. // Die C++ Standard Version: @@ -115,10 +118,9 @@ int main() // Argumente können per Standard für eine Funktion gesetzt werden, // wenn diese beim Aufruf nicht bereitgestellt werden. - void doSomethingWithInts(int a = 1, int b = 4) { - // führe Anweisungen mit "ints" aus. + // führe Anweisungen mit "int´s" aus. } int main() @@ -141,18 +143,18 @@ void invalidDeclaration(int a = 1, int b) // Fehler! // Namespaces stellen einen getrennten Gültigkeitsbereich für Variablen, // Funktionen und andere Deklarationen zur Verfügung. // Namespaces können geschachtelt werden. -namespace First +namespace First { - namespace Nested + namespace Nested { void foo() { printf("This is First::Nested::foo\n"); } - } // Ende des Namespaces "Nested" -} // Ende des Namespaces "First" + } // Ende des Namespace "Nested" +} // Ende des Namespace "First" -namespace Second +namespace Second { void foo() { @@ -236,8 +238,8 @@ cout << myString; // "Hello Dog" // C++ besitzt _Referenzen_. // Diese sind Pointer-Typen, welche nicht erneut zugewiesen werden können // und nicht Null sein können. -// Sie besitzen den selben Synthax wie Variablen. -// Für die Dereferenzierung ist kein * notwendig und +// Sie besitzen den selben Syntax wie Variablen. +// Für die Dereferenzierung ist kein * notwendig und // & (die Adresse) wird nicht für die Zuweisung verwendet. using namespace std; @@ -261,19 +263,18 @@ cout << fooRef; // Gibt "I am bar" aus // Die Adresse von fooRef verbleibt die selbe, sie verweist immer noch auf foo - const string& barRef = bar; // Erzeugt konstante Referenz auf bar. // Wie in C, können konstante Werte ( und Pointer bzw. Referenzen) nicht verändert werden. barRef += ". Hi!"; // Fehler: konstante Referenzen können nicht verändert werden. -// Hinweis: bevor wir genauer Referenzen besprechen, schauen wir uns zuerst ein Konzept an +// Hinweis: bevor wir genauer Referenzen besprechen, schauen wir uns zuerst ein Konzept an, // welches als "temporäres Objekt" bezeichnet wird. Gehen wir von folgenden Code aus: string tempObjectFun() { ... } string retVal = tempObjectFun(); // Was passiert nun in der zweiten Zeile: -// - ein String Objekt wird von tempObjectFun zurückgegeben +// - ein String Objekt wird von "tempObjectFun" zurückgegeben // - ein neuer String wird mit dem zurückgegebenen Objekt als Argument für den Konstruktor erzeugt. // - das zurückgegebene Objekt wird zerstört // Das zurückgegbene Objekt wird temporäres Objekt genannt. Temporäre Objekte werden erzeugt @@ -285,19 +286,20 @@ foo(bar(tempObjectFun())) // Nehmen wir an foo und bar existieren. Das Objekt wird von "tempObjectFun" zurückgegeben, // wird an bar übergeben und ist zerstört bevor foo aufgerufen wird. -// Zurück zu Referenzen. Die Ausnahme, dass die "am Ende des Ausdrucks" Regel ist gültig, -// wenn das temporäre Objekt an eine konstante Referenz gebunden ist, in welchem Fall das -// Leben auf den aktuellen Gültigkeitsbereich erweitert wird. +// Zurück zu Referenzen. Die Annahme, dass die "am Ende des Ausdrucks" Regel gültig ist, +// wenn das temporäre Objekt an eine konstante Referenz gebunden ist, ist der Fall, wenn die Lebensdauer +// auf den aktuellen Gültigkeitsbereich erweitert wird. void constReferenceTempObjectFun() { - // constRef erhält das temporäre Objekt und ist gültig bis ans Ende der Funktion + // constRef erhält das temporäre Objekt und ist gültig bis ans Ende der Funktion const string& constRef = tempObjectFun(); ... } -// Eine andere Art von Referenzen wird in C++11 eingeführt und ist speziell für -// temporäre Objekte. Es ist nicht möglich Variablen des Typs zu besitzen, aber -// Vorrechte bei der Auflösung. +// Eine andere Art von Referenzen wurde in C++11 eingeführt und ist speziell für +// temporäre Objekte. Es ist nicht möglich Variablen des Typs zu besitzen, aber +// Vorrechte bei der Auflösung zu besitzen. + void someFun(string& s) { ... } // Reguläre Referenz void someFun(string&& s) { ... } // Referenz auf ein temporäres Objekt @@ -310,8 +312,8 @@ someFun(tempObjectFun()); // Ruft die Funktion mit der temporären Referenz auf basic_string(const basic_string& other); basic_string(basic_string&& other); -// Nehmen wir an, wir erzeugen einen neuen String eines temporären Objekts (welches später -// zerstört wird), hierbei existiert ein effizienterer Konstruktor. Dieses Konzept wird +// Nehmen wir an, wir erzeugen einen neuen String eines temporären Objekts (welches später +// zerstört wird), hierbei existiert ein effizienterer Konstruktor. Dieses Konzept wird // als "move semantics" bezeichnet (bewegen eines Objekts in ein anderes in C++). ///////////////////// @@ -346,18 +348,18 @@ enum ECarTypes : uint8_t void WriteByteToFile(uint8_t InputValue) { - // Serialisierung von InputValue in eine Datei + // Serialisierung von "InputValue" in eine Datei } void WritePreferredCarTypeToFile(ECarTypes InputCarType) { // Das enum wird implizit zu einem "uint8_t" konvertiert. Bedingt dadurch, dass - // es sich um ein enum handelt. + // es sich um ein "enum" handelt. WriteByteToFile(InputCarType); } -// Nicht immer ist es gewünscht, dass enums zu einem Integer oder zu einem anderen -// enum umgewandelt werden. Daher ist es möglich eine enum-Klasse zu erzeugen, welche +// Nicht immer ist es gewünscht, dass enum´s zu einem Integer oder zu einem anderen +// enum umgewandelt werden. Daher ist es möglich eine enum-Klasse zu erzeugen, welche // nicht implizit umgewandelt wird. enum class ECarTypes : uint8_t { @@ -374,8 +376,8 @@ void WriteByteToFile(uint8_t InputValue) void WritePreferredCarTypeToFile(ECarTypes InputCarType) { - // Wird nicht kompilieren, da ECarTypes ein "uint8_t" ist, da das enum - // als "enum class" deklariert wurde! + // Wird nicht kompilieren, da "ECarTypes" ein "uint8_t" ist, da das enum + // als "enum class" deklariert wurde! WriteByteToFile(InputCarType); } @@ -401,15 +403,15 @@ public: // Standard Konstruktor Dog(); - // Member-Funktonensdeklaration (Implementierung folgt) + // Member-Funktionsdeklaration (Implementierung folgt). // Bemerkung: std::string statt der Verwendung von namespace std; // "using namespace" sollte niemals in einem header verwendet werden. void setName(const std::string& dogsName); void setWeight(int dogsWeight); - // Funktionen, die Objekte nicht ändern sollte mit const deklariert werden. - // Funktionen müssen explizit als "virtual" deklariert werden, um in einer + // Funktionen, die Objekte nicht ändern, sollten mit const deklariert werden. + // Funktionen müssen explizit als "virtual" deklariert werden, um in einer // abgeleiteten Klassen überschrieben zu werden. // Aus performance Gründen sind Funktionen nicht per default virtual. virtual void print() const; @@ -419,24 +421,24 @@ public: void bark() const { std::cout << name << " barks!\n"; } // Neben Konstruktoren, bietet C++ Destruktoren. - // Diese werden aufgerufen, wenn ein Objekt freigegeben wird oder - // seinen Wertebereich verlässt. + // Diese werden aufgerufen, wenn ein Objekt freigegeben wird oder + // seinen Wertebereich verlässt. // Dies ermöglicht mächtige Paradigmen, wie auch RAII. // Destruktoren sollten virtual sein, wenn eine Klasse von ihr // abgeleitet wird. Ist dieser nicht virtual, dann wird der - // Destruktor der abgeleiteten Klasse nicht aufgerufen, insofern + // Destruktor der abgeleiteten Klasse nicht aufgerufen, insofern // das Objekt durch eine Referenz/Pointer der Basisklasse entfernt wird. virtual ~Dog(); }; // Ein Semikolon schließt die Definition der Klasse ab. -// Klassen-Member-Funktionen sind üblicherweise in der .cpp Datei implmentiert. +// Klassen-Member-Funktionen sind üblicherweise in der .cpp Datei implementiert. Dog::Dog() { std::cout << "A dog has been constructed\n"; } -// Objekte sollten als Referenz übergeben werden und wenn diese nicht +// Objekte sollten als Referenz übergeben werden und wenn diese nicht // verändert werden sollen, sollte das Objekt als const Referenz übergeben werden. void Dog::setName(const std::string& dogsName) { @@ -468,8 +470,6 @@ int main() return 0; } // Ausgabe: "Goodbye Barkley" -// Vererbung: - // Diese Klasse erbt alles was public bzw. protected ist von der Dog-Klasse // und darüber hinaus auch private Methoden/Attribute, jedoch kann auf diese // nicht direkt zugegriffen werden. Lediglich über public/procted getter/setter. @@ -481,7 +481,7 @@ public: // Überschreibt das Verhalten der "print" Funktion für alle "OwnedDogs". // Siehe: http://en.wikipedia.org/wiki/Polymorphism_(computer_science)#Subtyping // für eine grundlegende Einführung in "Subtype Polymorphismus". - // Das "override" Schlüsselwort ist optional, aber stellt sicher, dass die + // Das "override" Schlüsselwort ist optional, aber stellt sicher, dass die // Methode der Basisklasse tatsächlich überschrieben wurde. void print() const override; @@ -555,7 +555,7 @@ Point& Point::operator+=(const Point& rhs) return *this; } -int main () +int main () { Point up (0,1); Point right (1,0); @@ -574,23 +574,23 @@ int main () // Templates in C++ werden in erster Linie dafür verwendet generisch zu programmieren. // Sie unterstützen explizite und partielle Spezialisierung und darüber hinaus können // sie für funktionale Klassen verwendet werden. -// Tatsächlich bilden templates die Turing-Vollständigkeit +// Tatsächlich bilden templates die Turing-Vollständigkeit // (universelle Programmierbarkeit) ab. // Zu Beginn ein einführendes Beispiel der generischen Programmierung. // Die Definition einer Klasse bzw. Funktion, welche mit dem Typ T parametriert wird. template -class Box +class Box { public: // T repräsentiert an dieser Stelle einen beliebigen Typen. void insert(const T&) { ... } }; -// Während der Kompilierung generiert der Kompiler Kopien für jedes Template, wobei -// hierbei die Parameter substituiert werden. Somit muss bei jedem Aufruf die gesamte -// Definition der Klasse zur Verfügung stehen. Aus diesem Grund wird ein Template +// Während der Kompilierung generiert der Compiler Kopien für jedes template, wobei +// hierbei die Parameter substituiert werden. Somit muss bei jedem Aufruf die gesamte +// Definition der Klasse zur Verfügung stehen. Aus diesem Grund wird ein Template // komplett im header definiert. // Erzeugung einer Template-Klasse auf dem stack: @@ -609,7 +609,7 @@ boxOfBox.insert(intBox); // Manchmal ist folgende Notation anzutreffen: // template // Das 'class' Schlüsselwort und das 'typename' Schlüsselwort -// sind fast identisch hinsichtlich der Funktionalität. Weitere +// sind fast identisch hinsichtlich der Funktionalität. Weitere // Informationen auf: http://en.wikipedia.org/wiki/Typename // Eine template-Funktion: @@ -623,7 +623,7 @@ void barkThreeTimes(const T& input) // Hierbei ist zu beachten, dass an dieser Stelle nichts über den Typen des Parameters // definiert wurde. Der Kompiler wird bei jedem Aufruf bzw. jeder Erzeugung den Typen -// prüfen. Somit funktioniert die zuvor definiert Funktion für jeden Typ 'T', die die +// prüfen. Somit funktioniert die zuvor definierte Funktion für jeden Typ 'T', die die // const Methode 'bark' implementiert hat. Dog fluffy; @@ -632,14 +632,14 @@ barkThreeTimes(fluffy); // Gibt "Fluffy barks" dreimal aus. // Template Parameter müssen keine Klassen sein. template -void printMessage() +void printMessage() { cout << "Learn C++ in " << Y << " minutes!" << endl; } // Des Weiteren können templates aus Effizienzgründen genauer spezifiziert werden. // Selbstverständlich sind reale-Problemen, welche genauer spezifiziert werden nicht -// derart trivial. Auch wenn alle Parameter explizit definiert wurden, muss die +// derart trivial. Auch wenn alle Parameter explizit definiert wurden, muss die // Funktion oder Klasse als template deklariert werden. template<> void printMessage<10>() @@ -655,17 +655,17 @@ printMessage<10>(); // Gibt "Learn C++ faster in only 10 minutes!" aus. // Ausnahme Behandlungen (Exception-Handling) ///////////////////// -// Die Standard Bibliothek bietet einige Exceptions. +// Die Standard Bibliothek bietet einige exceptions. // Siehe: http://en.cppreference.com/w/cpp/error/exception. -// Grundsätzlich können alle Typen als Exception geworfen werden. +// Grundsätzlich können alle Typen als exception geworfen werden. #include #include -// Alle Exceptions, die in dem "try" Block geworfen werden, können mittels +// Alle exceptions, die in dem "try" Block geworfen werden, können mittels // "catch" abgefangen werden. -try +try { - // Exceptions sollten nicht auf dem heap mithilfe + // exceptions sollten nicht auf dem heap mithilfe // von "new" allokiert werden. throw std::runtime_error("A problem occurred"); } @@ -690,7 +690,7 @@ catch (...) // RAII steht für "Resource Acquisition Is Initialization". // Oft wird dies als eines der wichtigsten Paradigmen in C++ betrachtet. -// RAII beschreibt das Konzept, dass der Konstruktor für ein Objekt +// RAII beschreibt das Konzept, dass der Konstruktor für ein Objekt // die Ressourcen akquiriert und der Destruktor diese freigibt. // Zum Verständnis, warum dies sinnvoll ist, nachfolgend @@ -726,7 +726,7 @@ bool doSomethingWithAFile(const char* filename) return false; // Fehler "melden". } - if (!doSomethingElseWithIt(fh)) + if (!doSomethingElseWithIt(fh)) { fclose(fh); // File handle schließen. return false; // Fehler "melden". @@ -770,12 +770,12 @@ void doSomethingWithAFile(const char* filename) doSomethingWithTheFile(fh); doSomethingElseWithIt(fh); } - catch (...) + catch (...) { - // Im Fehlerfall sollte sichergestellt sein, dass die + // Im Fehlerfall sollte sichergestellt sein, dass die // Datei geschlossen wird. - fclose(fh); - throw; // Erneutes werfen der Exception + fclose(fh); + throw; // Erneutes werfen der exception } fclose(fh); // Schließen der Datei @@ -796,7 +796,7 @@ void doSomethingWithAFile(const std::string& filename) } // Die Datei wird automatisch vom Destruktor geschlossen. // Diese Vorgehensweise bietet massive Vorteile: -// 1. Egal was passiert, die Ressource (das Datei-Handle) wird aufgelöst, +// 1. Egal was passiert, die Ressource (das Datei-Handle) wird aufgelöst, // insofern der Destruktor korrekt beschrieben wurde. Es ist möglich // zu vergessen das Datei-Handle zu schließen, was zu einem "leak" der // entsprechenden Ressource führt. @@ -804,13 +804,13 @@ void doSomethingWithAFile(const std::string& filename) // Der Destruktor wird das Datei-Handle im Hintergrund schließen und der // Programmierer muss sich darum keinerlei Sorgen machen. // 3. Der Code ist "exception sicher". -// Egal wo die exception geworfen wird, das Aufäumen wird definitv vollzogen. +// Egal wo die exception geworfen wird, das Aufräumen wird definitiv vollzogen. // Der gesamte idiomatische C++ Code verwendet RAII für alle Ressourcen. // Weitere Beispiele: // - Speicher verwenden "unique_ptr" und "shared_ptr". // - Container - verkettete Listen (linked list), vector (selbst organisierende -// Arrays), hash maps, etc., entfernen deren Inhalt, wenn diese außerhalb des +// Arrays), hash maps, etc., entfernen deren Inhalt, wenn diese außerhalb des // Gültigkeitsbereichs laufen. // - Mutex´s verwenden lock_guard und unique_lock. @@ -818,7 +818,7 @@ void doSomethingWithAFile(const std::string& filename) // Container ///////////////////// -// Die Container der Standard Tenplate Bibliothek beinhaltet einige vordefinierter templates. +// Die Container der Standard template Bibliothek beinhaltet einige vordefinierter templates. // Diese verwalten die Speicherbereiche für die eigenen Elemente und stellen Member-Funktionen // für den Zugriff und die Maniplulation bereit. @@ -842,7 +842,7 @@ for (int i = 0; i < my_vector.size(); i++) // Oder die Verwendung von Iteratoren: vector::iterator it; // Initialisierng des Iterators. -for (it = my_vector.begin(); it != my_vector.end(); ++it) +for (it = my_vector.begin(); it != my_vector.end(); ++it) { cout << *it << endl; } @@ -861,13 +861,13 @@ ST.insert(30); // Einfügen des Werts 30 in das Set ST // 10 20 30 // Entfernen eines Elements: -ST.erase(20); +ST.erase(20); // Set ST: 10 30 // Für das iterieren verwenden wir Iteratoren: set::iterator it; -for(it=ST.begin();it('A',1)); // Einfügen des Werts "1" für den Key "A" mymap.insert(pair('Z',26)); // Einfügen des Werts "26" für den Key "Z". -// Das Iterieren über Maps: +// Das Iterieren über Maps: map::iterator it; for (it=mymap.begin(); it!=mymap.end(); ++it) std::cout << it->first << "->" << it->second << '\n'; @@ -918,25 +918,25 @@ cout << it->second; // sind effizienter und benötigen keine Reihenfolge. "unordered_maps" sind ab // C++11 verfügbar. -// Container für nicht-primitve Datentypen benötigen Vergleichsfunktionen im Objekt selbst, +// Container für nicht-primitive Datentypen benötigen Vergleichsfunktionen im Objekt selbst, // oder als Funktionspointer. Primitive Datentypen besitzen default-Vergleichsfunktionen. // Allerdings können diese überschrieben werden. -class Foo +class Foo { public: int j; Foo(int a) : j(a) {} }; -struct compareFunction +struct compareFunction { - bool operator()(const Foo& a, const Foo& b) const + bool operator()(const Foo& a, const Foo& b) const { return a.j < b.j; } }; -// Folgender Code ist nicht valide, könnte aber von einigen Compilern +// Folgender Code ist nicht valide, könnte aber von einigen Compilern // als valide angesehen werden: // std::map fooMap; std::map fooMap; @@ -949,10 +949,10 @@ fooMap.find(Foo(1)); // Wahr /////////////////////////////////////// // Lambdas sind eine gängige Methodik um anonyme Funktionen an dem -// Ort der Verwendung zu definieren. Darüber hinaus auch bei der +// Ort der Verwendung zu definieren. Darüber hinaus auch bei der // Verwendung von Funktionen als Argument einer Funktion. -// Nehmen wir an es soll ein Vektor von "pairs" (Paaren) mithilfe +// Nehmen wir an es soll ein Vektor von "pairs" (Paaren) mithilfe // des zweiten Werts des "pairs" sortiert werden. vector > tester; @@ -968,19 +968,19 @@ sort(tester.begin(), tester.end(), [](const pair& lhs, const pair dog_ids; -for(int i = 0; i < 3; i++) +for(int i = 0; i < 3; i++) { dog_ids.push_back(i); } @@ -1013,8 +1013,7 @@ for(int elem: arr) } // Insofern "auto" verwendet wird, muss der Typ nicht weiter beachtet werden. - -for(auto elem: arr) +for(auto elem: arr) { // Anweisungen ... } @@ -1029,18 +1028,17 @@ for(auto elem: arr) // C++ ist eine der Sprachen, bei der es ein leichtes ist sich selbst ins Bein zu schießen. // Private-Methoden können überschrieben werden -class Foo +class Foo { virtual void bar(); }; -class FooSub : public Foo +class FooSub : public Foo { virtual void bar(); // Überschreibt Foo::bar! }; - -// 0 == false == NULL +// 0 == false == NULL bool* pt = new bool; *pt = 0; // Setzt den Wert des Pointers 'pt' auf false. pt = 0; // Setzt 'pt' auf den "null-pointer". Keine Compiler-Warnung. @@ -1050,18 +1048,17 @@ int* pt2 = new int; *pt2 = nullptr; // Kompiliert nicht. pt2 = nullptr; // Setzt pt2 auf null. -// Eine Ausnahme bilden bools. +// Eine Ausnahme bilden bool´s. // Dies erlaubt es "null-pointer" zu testen: if(!ptr) // Die Konsequenz ist jedoch, dass dem nullptr ein bool zugewiesen werden kann. -*pt = nullptr; // Kompiliert auch wenn '*pt' ein bool ist! - +*pt = nullptr; // Kompiliert auch, wenn '*pt' ein bool ist! // '=' != '=' != '='! // Ruft Foo::Foo(const Foo&) auf, oder den Kopierkonstruktor Foo f2; Foo f1 = f2; -// Ruft Foo::Foo(const Foo&) auf, aber kopiert lediglich den "Foo" Teil von +// Ruft Foo::Foo(const Foo&) auf, aber kopiert lediglich den "Foo" Teil von // "fooSub". Alle zusätzlichen Member werden verworfen. Diese eigenartige Verhalten // wird auch "object slicing" genannt. FooSub fooSub; @@ -1077,10 +1074,10 @@ f1 = f2; #include -// Konzeptionell sind Tuples alten Datenstrukturen sehr ähnlich, allerdings haben diese keine -// benamten Daten-Member, sondern werden durch die Reihenfolge angesprochen. +// Konzeptionell sind Tuple´s alten Datenstrukturen sehr ähnlich, allerdings haben diese keine +// bezeichneten Daten-Member, sondern werden durch die Reihenfolge angesprochen. -// Erstellen des Tuples und das Einfügen eines Werts. +// Erstellen des Tuples und das Einfügen eines Werts. auto first = make_tuple(10, 'A'); const int maxN = 1e9; const int maxL = 15; @@ -1122,8 +1119,7 @@ cout << get<5>(concatenated_tuple) << "\n"; // Ausgabe: 'A' // Die meisten Operatoren in C++ entsprechen denen aus anderen Sprachen // Logische Operatoren. - -// C++ verwendet so genannte "Short-circuit" Evaluierung für boolean-Ausdrücke. +// C++ verwendet so genannte "Short-circuit" Evaluierung für Boolean-Ausdrücke. // Das zweite Argument wird ausgeführt bzw. evaluiert, wenn das erste Argument genügt, // um den Ausdruck zu bestimmen.