Zunächst einige Faustregeln:
Verwendung std::unique_ptrals intelligenter No-Overhead-Zeiger. Sie sollten sich nicht allzu oft mit rohen Zeigern herumschlagen müssen. std::shared_ptrist in den meisten Fällen ebenfalls unnötig. Der Wunsch nach gemeinsamem Eigentum verrät oftmals, dass man überhaupt nicht an Eigentum denkt.
Verwendung std::arrayfür Arrays mit statischer Länge und std::vectorfür dynamische Arrays .
Verwenden Sie generische Algorithmen in großem Umfang, insbesondere:
<algorithm>
<numeric>
<iterator>
<functional>
Verwendung autound decltype()wo immer sie der Lesbarkeit zugute kommen. Insbesondere, wenn Sie eine Sache deklarieren möchten, aber einen Typ, den Sie nicht interessieren, wie z. B. einen Iterator oder einen komplexen Vorlagentyp, verwenden Sie auto. Wenn Sie eine Sache in Bezug auf die Art einer anderen Sache deklarieren möchten, verwenden Sie decltype().
Machen Sie Dinge typsicher, wenn Sie können. Wenn Sie Behauptungen haben, die Invarianten für eine bestimmte Sache erzwingen, kann diese Logik in einem Typ zentralisiert werden. Dies bedeutet nicht unbedingt einen zusätzlichen Aufwand für die Laufzeit. Es sollte auch selbstverständlich sein, dass C-Casts ( (T)x) sollen mich für die explizit C ++ zu vermeiden (und durchsuchbar!) - Casts (zB static_cast).
Schließlich wissen, wie die Regel von drei:
- Zerstörer
- Konstruktor kopieren
- Aufgabenverwalter
Wurde die Regel von fünf mit der Hinzufügung des Verschiebungskonstruktors und des Verschiebungszuweisungsoperators. Und verstehen Sie rvalue-Referenzen im Allgemeinen und wie Sie das Kopieren vermeiden.
C ++ ist eine komplexe Sprache, so dass es schwierig ist , zu charakterisieren , wie am besten nutzen alle davon. Aber die Praktiken einer guten C ++ - Entwicklung haben sich mit C ++ 11 nicht grundlegend geändert. Sie sollten weiterhin speicherverwaltete Container der manuellen Speicherverwaltung vorziehen. Intelligente Zeiger erleichtern dies auf effiziente Weise.
Ich würde sagen, dass modernes C ++ tatsächlich größtenteils frei von manueller Speicherverwaltung ist. Der Vorteil des C ++ - Speichermodells besteht darin, dass es deterministisch und nicht manuell ist. Vorhersehbare Aufhebungen sorgen für eine vorhersehbarere Leistung.
Was einen Compiler angeht, so sind sowohl G ++ als auch Clang in Bezug auf C ++ 11-Funktionen wettbewerbsfähig und können ihre Mängel rasch beheben. Ich benutze kein Visual Studio, daher kann ich weder dafür noch dagegen sprechen.
Zum Schluss noch ein Hinweis zu std::for_each: Vermeiden Sie es generell.
transform, accumulateUnd erase- remove_ifsind gute alte funktionale map, foldund filter. Ist for_eachaber allgemeiner und daher weniger aussagekräftig - es drückt keine andere Absicht als Schleifen aus. Außerdem wird es in den gleichen Situationen wie bereichsbasiert verwendet forund ist syntaktisch schwerer, selbst wenn es ohne Punkte verwendet wird. Erwägen:
for (const auto i : container)
std::cout << i << '\n';
std::for_each(container.begin(), container.end(), [](int i) {
std::cout << i << '\n';
});
for (const auto i : container)
frobnicate(i);
std::for_each(container.begin(), container.end(), frobnicate);