Scott Meyers Mehr Effektiv C++ programmieren 35 neue Wege zur Verbesserung Ihrer Programme und Entwürfe Deutsche Übersetzung von Markus Beringmeier ^ ADDISON-WESLEY An imprint of Addison Wesley Longman, Inc. Bonn Reading, Massachusetts Menlo Park, California New York Harlow, England Don Mills, Ontario Sydney Mexico City Madrid Amsterdam
Vorwort des Übersetzers 9 Danksagungen 11 Die Richtlinien 11 Das Buch 13 Die Menschen 14 Einführung 15 Das C++ in»effektiver C++ programmieren«16 Konventionen und Terminologie 18 Hinweise auf Fehler, Verbesserungsvorschläge, Korrekturen 21 1 Grundlagen 23 1.1 Richtlinie 1: Der Unterschied zwischen Zeigern und Referenzen 23 1.2 Richtlinie 2: Bevorzuge C++-Casts vor dem C-Cast 26 1.3 Richtlinie 3: Mische niemals Vektoren und Polymorphie 30 1.4 Richtlinie 4: Vermeide grundlose Standardkonstruktoren 33 2 Operatoren 39 2.1 Richtlinie 5: Sei vorsichtig bei benutzerdefinierten Umwandlungen 39 2.2 Richtlinie 6: Unterscheide Präfix und Postfix des Inkrement- und Dekrementoperators 46 2.3 Richtlinie 7: Überlade niemals &&, I I oder, 49 2.4 Richtlinie 8: Verstehe die unterschiedlichen Bedeutungen von new und delete 52 2.4.1 Placement new 53 2.4.2 Löschen und Speicherrückgabe 55 2.4.3 Vektoren 56 3 Exceptions (Ausnahmebedingungen) 59 3.1 Richtlinie 9: Benutze Destruktoren, um Ressourcenlecks zu verhindern 60 3.2 Richtlinie 10: Verhindere Ressourcenlecks in Konstruktoren 65
3.3 Richtlinie 11: Verhindere Exceptions bei Destruktoren 73 3.4 Richtlinie 12: Verstehe, wie sich das Werfen einer Exception von der Parameterübergabe oder von einem virtuellen Funktionsaufruf unterscheidet 76 3.5 Richtlinie 13: Fange Exceptions per Referenz 83 3.6 Richtlinie 14: Benutze Exceptionspezifikationen mit Bedacht 87 3.7 Richtlinie 15: Verstehe die Kosten der Exceptionbehandlung 93 Effizienz 97 4.1 Richtlinie 16: Denke an die 80-20-Regel 98 4.2 Richtlinie 17: Erwäge Lazy Evaluation (verzögerte Berechnung) 100 4.2.1 Reference Counting (Referenzzählung) 101 4.2.2 Lesen vom Schreiben unterscheiden 102 4.2.3 Lazy Fetching (verzögertes Holen) 103 4.2.4 Lazy Expression Evaluation (Verzögerte Bewertung von Ausdrücken) 106 4.2.5 Zusammenfassung 108 4.3 Richtlinie 18: Spare die Kosten erwarteter Berechnungen 109 4.4 Richtlinie 19: Verstehe den Ursprung temporärer Objekte 114 4.5 Richtlinie 20: Ermögliche die Returnwertoptimierung 117 4.6 Richtlinie 21: Nutze Überladung, um implizite Umwandlungen zu vermeiden 120 4.7 Richtlinie 22: Erwäge die Benutzung von op= anstelle eines einzigen Operators 123 4.8 Richtlinie 23: Erwäge die Benutzung anderer Bibliotheken 126 4.9 Richtlinie 24: Verstehe die Kosten virtueller Funktionen, Mehrfachvererbung, virtueller Basisklassen und RTTI 129 Techniken 139 5.1 Richtlinie 25: Virtuelle Konstruktoren und Nichtmemberfunktionen 139 5.1.1 Nichtmemberfunktionen virtuell machen 144 5.2 Richtlinie 26: Die Anzahl von Objekten einer Klasse begrenzen 146 5.2.1 Keins oder nur ein Objekt erlauben 146 5.2.2 Zusammenhänge der Objekt-Konstruktion 151 5.2.3 Objekte dürfen kommen und gehen 153 5.2.4 Eine Basisklasse für Objekt-Zählung 157 5.3 Richtlinie 27 Wie man Objekte auf dem Heap verhindert oder erzwingt 160 5.3.1 Heapbasierte Objekte erzwingen 160 5.3.2 Feststellen, ob ein Objekt auf dem Heap ist 163 5.3.3 Heapbasierte Objekte verhindern 172 5.4 Richtlinie 28: Smart Pointer (intelligente Zeiger) 173
7 5.4.1 Konstruktion, Zuweisung und Destruktion von Smart Pointern 176 5.4.2 Implementation der Dereferenzierungsoperatoren 180 5.4.3 Wie man Smart Pointer auf Null testet 182 5.4.4 Smart Pointer in normale Zeiger umwandeln 184 5.4.5 Smart Pointer und vererbungsbasierte Typumwandlungen 188 5.4.6 Smart Pointer und const 193 5.4.7 Bewertung 196 5.5 Richtlinie 29: Reference Counting (Referenzzählung) 197 5.5.1 Implementierung der Referenzzählung 199 5.5.2 Copy-on-Write (beim Schreiben kopieren) 204 5.5.3 Zeiger, Referenzen und copy-on-write 205 5.5.4 Eine Basisklasse für Referenzzählung 208 5.5.5 Automatisierung der Manipulation des Referenzzählers 211 5.5.6 Alles zusammenbauen 216 5.5.7 Referenzzählung für existierende Klassen hinzufügen 221 5.5.8 Bewertung 225 5.6 Richtlinie 30: Proxy-Klassen 227 5.6.1 Implementierung zweidimensionaler Vektoren 228 5.6.2 bei operator[] Lesen vom Schreiben unterscheiden 230 5.6.3 Einschränkungen 236 5.6.4 Bewertung 241 5.7 Richtlinie 31: Funktionen abhängig von mehreren Objekten virtuell machen 241 5.7.1 Benutzung von virtuellen Funktionen und RTTI 243 5.7.2 Nur virtuelle Funktionen benutzen 245 5.7.3 Emulation virtueller Funktionstabellen 248 5.7.4 Initialisierung von emulierten virtuellen Funktionstabellen 252 5.7.5 Benutzung von Nichtmemberfunktionen, um Kollisionen zu behandeln 257 5.7.6 Vererbung und die Emulation virtueller Funktionstabellen 261 5.7.7 Initialisierung von emulierten virtuellen Funktionstabellen (verbesserte Version) 262 Vermischtes 265 6.1 Richtlinie 32: Programmiere mit Blick auf die Zukunft 265 6.2 Richtlinie 33: Mache Basisklasse abstrakt, die nicht am Ende der Hierarchie stehen 271 6.3 Richtlinie 34: Verstehe, wie man C++ und C kombiniert 283 6.3.1 Name Mangling (Namenszerstückelung) 283 6.3.2 Initialisierung von statischen Objekten 286 6.3.3 Dynamische Speicheranforderung 287 6.3.4 Kompatibilität der Datenstrukturen 288 6.3.5 Zusammenfassung 289 6.4 Richtlinie 35: Mach Dich vertraut mit dem Sprachstandard 289 6.4.1 Die Standard Template Library 292
s 7 Literaturempfehlungen vom Autor 297 8 Eine Implementierung von auto_ptr 303 Stichwortverzeichnis 307 Der Übersetzer 325