1
0
mirror of https://github.com/adambard/learnxinyminutes-docs.git synced 2025-08-07 07:16:42 +02:00

[C++/de] fixed wrong spelling (#3579)

* Added [C++/de]

* [C++/de] filename fixed.

* [C++/de] language code in filename added

* [C++/de] fixed wrong spelling

* [C++/en] smart pointer added
This commit is contained in:
LamdaLamdaLamda
2019-08-03 20:18:39 +02:00
committed by Divay Prakash
parent 7fca9b47a9
commit 41f2b7f168
2 changed files with 157 additions and 110 deletions

View File

@@ -761,7 +761,7 @@ failure:
// things are a little cleaner, but still sub-optimal. // things are a little cleaner, but still sub-optimal.
void doSomethingWithAFile(const char* filename) 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) if (fh == nullptr)
throw std::runtime_error("Could not open the file."); 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 // - 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<Dog> 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<Dog> doggo_one (new Dog());
std::shared_ptr<Dog> 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 // Containers
///////////////////// /////////////////////

View File

@@ -23,9 +23,11 @@ entworfen wurde um,
- generische Programmierung zu unterstützen - generische Programmierung zu unterstützen
Durch seinen Syntax kann sie durchaus schwieriger und komplexer als neuere Sprachen sein. 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 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 Diese Kombination aus Geschwindigkeit und Funktionalität bildet C++ und ist eine der
weitverbreitesten Programmiersprachen. weitverbreitesten Programmiersprachen.
@@ -34,11 +36,12 @@ weitverbreitesten Programmiersprachen.
// Vergleich zu C // Vergleich zu C
////////////////// //////////////////
// C++ ist fast eine Untermenge von C and teilt sich grundsätzlich den // C ist fast eine Untermenge von C++ und teilt sich grundsätzlich den
// Syntax für Variablen Deklarationen, primitiven Typen und Funktionen. // Syntax für Variablen Deklarationen, primitiven Typen und Funktionen.
// Wie in C ist der Programmeinsprungpunkt eine Funktion, welche "main" genannt wird und // 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. // Dieser Wert fungiert als Beendigungsstatus des Programms.
// Siehe: https://de.wikipedia.org/wiki/Return_Code für weitere Informationen // Siehe: https://de.wikipedia.org/wiki/Return_Code für weitere Informationen
int main(int argc, char** argv) int main(int argc, char** argv)
@@ -46,7 +49,7 @@ int main(int argc, char** argv)
// Kommandozeilen Argumente werden genauso wie in C über argc und argv übergeben // 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. // 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 // Argc und argv können, wenn nicht benötigt, weg gelassen werden, indem
// die Funktionssignatur "int main()" verwendet wird. // die Funktionssignatur "int main()" verwendet wird.
@@ -54,12 +57,12 @@ int main(int argc, char** argv)
return 0; 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 sizeof('c') == sizeof(char) == 1
// In C sind Zeichen-Literale ints // In C sind Zeichen-Literale int´s
sizeof('c') == sizeof(int) sizeof('c') == sizeof(int)
// C++ verwendet striktes prototyping // C++ verwendet striktes prototyping
@@ -71,7 +74,7 @@ void func(); // Funktion mit beliebiger Anzahl von Argumenten
// Verwende nullptr, anstatt von NULL!!! // Verwende nullptr, anstatt von NULL!!!
int* ip = nullptr; int* ip = nullptr;
// C standard headers sind in C++ verfügbar. // C standard header sind in C++ verfügbar.
// C header enden mit .h, während // C header enden mit .h, während
// C++ header das Präfix "c" besitzen und kein ".h" Suffix verwenden. // C++ header das Präfix "c" besitzen und kein ".h" Suffix verwenden.
@@ -115,10 +118,9 @@ int main()
// Argumente können per Standard für eine Funktion gesetzt werden, // Argumente können per Standard für eine Funktion gesetzt werden,
// wenn diese beim Aufruf nicht bereitgestellt werden. // wenn diese beim Aufruf nicht bereitgestellt werden.
void doSomethingWithInts(int a = 1, int b = 4) void doSomethingWithInts(int a = 1, int b = 4)
{ {
// führe Anweisungen mit "ints" aus. // führe Anweisungen mit "int´s" aus.
} }
int main() int main()
@@ -149,8 +151,8 @@ namespace First
{ {
printf("This is First::Nested::foo\n"); printf("This is First::Nested::foo\n");
} }
} // Ende des Namespaces "Nested" } // Ende des Namespace "Nested"
} // Ende des Namespaces "First" } // Ende des Namespace "First"
namespace Second namespace Second
{ {
@@ -236,7 +238,7 @@ cout << myString; // "Hello Dog"
// C++ besitzt _Referenzen_. // C++ besitzt _Referenzen_.
// Diese sind Pointer-Typen, welche nicht erneut zugewiesen werden können // Diese sind Pointer-Typen, welche nicht erneut zugewiesen werden können
// und nicht Null sein können. // und nicht Null sein können.
// Sie besitzen den selben Synthax wie Variablen. // Sie besitzen den selben Syntax wie Variablen.
// Für die Dereferenzierung ist kein * notwendig und // Für die Dereferenzierung ist kein * notwendig und
// & (die Adresse) wird nicht für die Zuweisung verwendet. // & (die Adresse) wird nicht für die Zuweisung verwendet.
@@ -261,19 +263,18 @@ cout << fooRef; // Gibt "I am bar" aus
// Die Adresse von fooRef verbleibt die selbe, sie verweist immer noch auf foo // Die Adresse von fooRef verbleibt die selbe, sie verweist immer noch auf foo
const string& barRef = bar; // Erzeugt konstante Referenz auf bar. const string& barRef = bar; // Erzeugt konstante Referenz auf bar.
// Wie in C, können konstante Werte ( und Pointer bzw. Referenzen) nicht verändert werden. // 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. 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: // welches als "temporäres Objekt" bezeichnet wird. Gehen wir von folgenden Code aus:
string tempObjectFun() { ... } string tempObjectFun() { ... }
string retVal = tempObjectFun(); string retVal = tempObjectFun();
// Was passiert nun in der zweiten Zeile: // 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. // - 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ückgegebene Objekt wird zerstört
// Das zurückgegbene Objekt wird temporäres Objekt genannt. Temporäre Objekte werden erzeugt // Das zurückgegbene Objekt wird temporäres Objekt genannt. Temporäre Objekte werden erzeugt
@@ -285,9 +286,9 @@ foo(bar(tempObjectFun()))
// Nehmen wir an foo und bar existieren. Das Objekt wird von "tempObjectFun" zurückgegeben, // 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. // 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, // 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, in welchem Fall das // wenn das temporäre Objekt an eine konstante Referenz gebunden ist, ist der Fall, wenn die Lebensdauer
// Leben auf den aktuellen Gültigkeitsbereich erweitert wird. // auf den aktuellen Gültigkeitsbereich erweitert wird.
void constReferenceTempObjectFun() { 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
@@ -295,9 +296,10 @@ void constReferenceTempObjectFun() {
... ...
} }
// Eine andere Art von Referenzen wird in C++11 eingeführt und ist speziell für // 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 // temporäre Objekte. Es ist nicht möglich Variablen des Typs zu besitzen, aber
// Vorrechte bei der Auflösung. // Vorrechte bei der Auflösung zu besitzen.
void someFun(string& s) { ... } // Reguläre Referenz void someFun(string& s) { ... } // Reguläre Referenz
void someFun(string&& s) { ... } // Referenz auf ein temporäres Objekt void someFun(string&& s) { ... } // Referenz auf ein temporäres Objekt
@@ -346,17 +348,17 @@ enum ECarTypes : uint8_t
void WriteByteToFile(uint8_t InputValue) void WriteByteToFile(uint8_t InputValue)
{ {
// Serialisierung von InputValue in eine Datei // Serialisierung von "InputValue" in eine Datei
} }
void WritePreferredCarTypeToFile(ECarTypes InputCarType) void WritePreferredCarTypeToFile(ECarTypes InputCarType)
{ {
// Das enum wird implizit zu einem "uint8_t" konvertiert. Bedingt dadurch, dass // 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); WriteByteToFile(InputCarType);
} }
// Nicht immer ist es gewünscht, dass enums zu einem Integer oder zu einem anderen // 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 // enum umgewandelt werden. Daher ist es möglich eine enum-Klasse zu erzeugen, welche
// nicht implizit umgewandelt wird. // nicht implizit umgewandelt wird.
enum class ECarTypes : uint8_t enum class ECarTypes : uint8_t
@@ -374,8 +376,8 @@ void WriteByteToFile(uint8_t InputValue)
void WritePreferredCarTypeToFile(ECarTypes InputCarType) void WritePreferredCarTypeToFile(ECarTypes InputCarType)
{ {
// Wird nicht kompilieren, da ECarTypes ein "uint8_t" ist, da das enum // Wird nicht kompilieren, da "ECarTypes" ein "uint8_t" ist, da das enum
// als "enum class" deklariert wurde! // als "enum class" deklariert wurde!
WriteByteToFile(InputCarType); WriteByteToFile(InputCarType);
} }
@@ -401,14 +403,14 @@ public:
// Standard Konstruktor // Standard Konstruktor
Dog(); Dog();
// Member-Funktonensdeklaration (Implementierung folgt) // Member-Funktionsdeklaration (Implementierung folgt).
// Bemerkung: std::string statt der Verwendung von namespace std; // Bemerkung: std::string statt der Verwendung von namespace std;
// "using namespace" sollte niemals in einem header verwendet werden. // "using namespace" sollte niemals in einem header verwendet werden.
void setName(const std::string& dogsName); void setName(const std::string& dogsName);
void setWeight(int dogsWeight); void setWeight(int dogsWeight);
// Funktionen, die Objekte nicht ändern sollte mit const deklariert werden. // Funktionen, die Objekte nicht ändern, sollten mit const deklariert werden.
// Funktionen müssen explizit als "virtual" deklariert werden, um in einer // Funktionen müssen explizit als "virtual" deklariert werden, um in einer
// abgeleiteten Klassen überschrieben zu werden. // abgeleiteten Klassen überschrieben zu werden.
// Aus performance Gründen sind Funktionen nicht per default virtual. // Aus performance Gründen sind Funktionen nicht per default virtual.
@@ -430,7 +432,7 @@ public:
}; // Ein Semikolon schließt die Definition der Klasse ab. }; // 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() Dog::Dog()
{ {
std::cout << "A dog has been constructed\n"; std::cout << "A dog has been constructed\n";
@@ -468,8 +470,6 @@ int main()
return 0; return 0;
} // Ausgabe: "Goodbye Barkley" } // Ausgabe: "Goodbye Barkley"
// Vererbung:
// Diese Klasse erbt alles was public bzw. protected ist von der Dog-Klasse // 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 // und darüber hinaus auch private Methoden/Attribute, jedoch kann auf diese
// nicht direkt zugegriffen werden. Lediglich über public/procted getter/setter. // nicht direkt zugegriffen werden. Lediglich über public/procted getter/setter.
@@ -588,7 +588,7 @@ public:
void insert(const T&) { ... } void insert(const T&) { ... }
}; };
// Während der Kompilierung generiert der Kompiler Kopien für jedes Template, wobei // 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 // 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 // Definition der Klasse zur Verfügung stehen. Aus diesem Grund wird ein Template
// komplett im header definiert. // komplett im header definiert.
@@ -623,7 +623,7 @@ void barkThreeTimes(const T& input)
// Hierbei ist zu beachten, dass an dieser Stelle nichts über den Typen des Parameters // 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 // 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. // const Methode 'bark' implementiert hat.
Dog fluffy; Dog fluffy;
@@ -655,17 +655,17 @@ printMessage<10>(); // Gibt "Learn C++ faster in only 10 minutes!" aus.
// Ausnahme Behandlungen (Exception-Handling) // 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. // 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 <exception> #include <exception>
#include <stdexcept> #include <stdexcept>
// 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. // "catch" abgefangen werden.
try try
{ {
// Exceptions sollten nicht auf dem heap mithilfe // exceptions sollten nicht auf dem heap mithilfe
// von "new" allokiert werden. // von "new" allokiert werden.
throw std::runtime_error("A problem occurred"); throw std::runtime_error("A problem occurred");
} }
@@ -775,7 +775,7 @@ void doSomethingWithAFile(const char* filename)
// Im Fehlerfall sollte sichergestellt sein, dass die // Im Fehlerfall sollte sichergestellt sein, dass die
// Datei geschlossen wird. // Datei geschlossen wird.
fclose(fh); fclose(fh);
throw; // Erneutes werfen der Exception throw; // Erneutes werfen der exception
} }
fclose(fh); // Schließen der Datei fclose(fh); // Schließen der Datei
@@ -804,7 +804,7 @@ void doSomethingWithAFile(const std::string& filename)
// Der Destruktor wird das Datei-Handle im Hintergrund schließen und der // Der Destruktor wird das Datei-Handle im Hintergrund schließen und der
// Programmierer muss sich darum keinerlei Sorgen machen. // Programmierer muss sich darum keinerlei Sorgen machen.
// 3. Der Code ist "exception sicher". // 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. // Der gesamte idiomatische C++ Code verwendet RAII für alle Ressourcen.
// Weitere Beispiele: // Weitere Beispiele:
@@ -818,7 +818,7 @@ void doSomethingWithAFile(const std::string& filename)
// Container // 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 // Diese verwalten die Speicherbereiche für die eigenen Elemente und stellen Member-Funktionen
// für den Zugriff und die Maniplulation bereit. // für den Zugriff und die Maniplulation bereit.
@@ -876,7 +876,7 @@ for(it=ST.begin();it<ST.end();it++)
// 10 // 10
// 30 // 30
// Zum leeren des gesmten Container wird die Methode // Zum leeren des gesamten Container wird die Methode
// Container._name.clear() verwendet. // Container._name.clear() verwendet.
ST.clear(); ST.clear();
cout << ST.size(); // Ausgabe der Set-Größe cout << ST.size(); // Ausgabe der Set-Größe
@@ -918,7 +918,7 @@ cout << it->second;
// sind effizienter und benötigen keine Reihenfolge. "unordered_maps" sind ab // sind effizienter und benötigen keine Reihenfolge. "unordered_maps" sind ab
// C++11 verfügbar. // 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. // oder als Funktionspointer. Primitive Datentypen besitzen default-Vergleichsfunktionen.
// Allerdings können diese überschrieben werden. // Allerdings können diese überschrieben werden.
class Foo class Foo
@@ -968,7 +968,7 @@ sort(tester.begin(), tester.end(), [](const pair<int, int>& lhs, const pair<int,
// Beachte den Syntax von Lambda-Ausdrücken. // Beachte den Syntax von Lambda-Ausdrücken.
// Die [] im Lambda Ausdruck werden für die Variablen verwendet. // Die [] im Lambda Ausdruck werden für die Variablen verwendet.
// Diese so genannte "Capture List" definiert, was außerhalb des Lambdas // Diese so genannte "capture list" definiert, was außerhalb des Lambdas,
// innerhalb der Funktion verfügbar sein soll und in welcher Form. // innerhalb der Funktion verfügbar sein soll und in welcher Form.
// Dies kann folgendes sein: // Dies kann folgendes sein:
// 1. ein Wert [x] // 1. ein Wert [x]
@@ -1013,7 +1013,6 @@ for(int elem: arr)
} }
// Insofern "auto" verwendet wird, muss der Typ nicht weiter beachtet werden. // Insofern "auto" verwendet wird, muss der Typ nicht weiter beachtet werden.
for(auto elem: arr) for(auto elem: arr)
{ {
// Anweisungen ... // Anweisungen ...
@@ -1039,7 +1038,6 @@ class FooSub : public Foo
virtual void bar(); // Überschreibt Foo::bar! virtual void bar(); // Überschreibt Foo::bar!
}; };
// 0 == false == NULL // 0 == false == NULL
bool* pt = new bool; bool* pt = new bool;
*pt = 0; // Setzt den Wert des Pointers 'pt' auf false. *pt = 0; // Setzt den Wert des Pointers 'pt' auf false.
@@ -1050,11 +1048,10 @@ int* pt2 = new int;
*pt2 = nullptr; // Kompiliert nicht. *pt2 = nullptr; // Kompiliert nicht.
pt2 = nullptr; // Setzt pt2 auf null. pt2 = nullptr; // Setzt pt2 auf null.
// Eine Ausnahme bilden bools. // Eine Ausnahme bilden bool´s.
// Dies erlaubt es "null-pointer" zu testen: if(!ptr) // Dies erlaubt es "null-pointer" zu testen: if(!ptr)
// Die Konsequenz ist jedoch, dass dem nullptr ein bool zugewiesen werden kann. // 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 // Ruft Foo::Foo(const Foo&) auf, oder den Kopierkonstruktor
@@ -1077,8 +1074,8 @@ f1 = f2;
#include<tuple> #include<tuple>
// Konzeptionell sind Tuples alten Datenstrukturen sehr ähnlich, allerdings haben diese keine // Konzeptionell sind Tuple´s alten Datenstrukturen sehr ähnlich, allerdings haben diese keine
// benamten Daten-Member, sondern werden durch die Reihenfolge angesprochen. // 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'); auto first = make_tuple(10, 'A');
@@ -1122,8 +1119,7 @@ cout << get<5>(concatenated_tuple) << "\n"; // Ausgabe: 'A'
// Die meisten Operatoren in C++ entsprechen denen aus anderen Sprachen // Die meisten Operatoren in C++ entsprechen denen aus anderen Sprachen
// Logische Operatoren. // 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, // Das zweite Argument wird ausgeführt bzw. evaluiert, wenn das erste Argument genügt,
// um den Ausdruck zu bestimmen. // um den Ausdruck zu bestimmen.