Mit dem neuen Standard gibt es neue Wege, Dinge zu tun, und viele sind schöner als die alten Wege, aber der alte Weg ist immer noch in Ordnung. Es ist auch klar, dass der neue Standard aus Gründen der Abwärtskompatibilität offiziell nicht sehr abwertet. Die Frage bleibt also:
Welche alten Codierungsmethoden sind C ++ 11-Stilen definitiv unterlegen, und was können wir jetzt stattdessen tun?
Wenn Sie darauf antworten, können Sie die offensichtlichen Dinge wie "Auto-Variablen verwenden" überspringen.
auto_ptr
ist auch veraltet.Antworten:
final
Bezeichner, um die Klassenableitung zu verhindernstd::auto_ptr
Werke aufgrund der erstklassigen Unterstützung für rvalue-Referenzen nicht mehr benötigt werden.shrink_to_fit()
Elementfunktion, die das Austauschen mit einer temporären Funktion überflüssig machen sollte.= delete
Syntax ist eine viel direktere Art zu sagen, dass eine bestimmte Funktionalität explizit verweigert wird. Dies gilt für das Verhindern der Heap-Zuweisung (dh=delete
für Mitgliederoperator new
), das Verhindern von Kopien, die Zuweisung usw.result_of
: Die Verwendung der Klassenvorlageresult_of
sollte durch ersetzt werdendecltype
. Ich denke,result_of
verwendet,decltype
wenn es verfügbar ist.NULL
sollte Code neu definiert werden alsnullptr
, aber siehe STLs Vortrag , um zu erfahren, warum sie sich dagegen entschieden haben.Ich denke, ich werde dort aufhören!
quelle
result_of
von der Liste streichen. Trotz der umständlichen Notwendigkeittypename
, denke ich,typename result_of<F(Args...)::type
kann es manchmal einfacher sein, sie zu lesen alsdecltype(std::declval<F>()(std::declval<Args>()...)
, und mit der Aufnahme von N3436 in das Arbeitspapier arbeiten beide für SFINAE (was früher ein Vorteil wardecltype
, denresult_of
das nicht bot)Zu einem bestimmten Zeitpunkt wurde argumentiert, dass man nach
const
Wert anstatt nur nach Wert zurückkehren sollte:Dies war in C ++ 98/03 größtenteils harmlos und hat möglicherweise sogar einige Fehler entdeckt, die wie folgt aussahen:
Die Rückkehr durch
const
ist in C ++ 11 jedoch kontraindiziert, da sie die Bewegungssemantik verhindert:Also einfach entspannen und codieren:
quelle
A& operator=(A o)&
anstelle von definierenA& operator=(A o)
. Diese verhindern die dummen Fehler und führen dazu, dass sich Klassen eher wie Basistypen verhalten und die Bewegungssemantik nicht verhindern.Sobald Sie aufgeben können
0
undNULL
dafür sindnullptr
, tun Sie dies!In nicht generischem Code ist die Verwendung von
0
oderNULL
nicht so eine große Sache. Sobald Sie jedoch anfangen, Nullzeigerkonstanten im generischen Code zu übergeben, ändert sich die Situation schnell. Wenn Sie0
an a übergeben,template<class T> func(T)
T
wird dies alsint
und nicht als Nullzeigerkonstante abgeleitet. Danach kann es nicht mehr in eine Nullzeigerkonstante konvertiert werden. Dies führt zu einem Sumpf von Problemen, die einfach nicht existieren, wenn das Universum nur verwendet wirdnullptr
.C ++ 11 ist nicht veraltet
0
undNULL
als Nullzeigerkonstanten. Aber Sie sollten so codieren, als ob es so wäre.quelle
std::nullptr_t
.0
oderNULL
für Nullzeiger").Sichere Bool-Sprache →
explicit operator bool()
.Konstrukteure für private Kopien (boost :: noncopyable) →
X(const X&) = delete
Simulation der letzten Klasse mit privatem Destruktor und virtueller Vererbung →
class X final
quelle
Eines der Dinge, die Sie nur vermeiden, grundlegende Algorithmen in C ++ 11 zu schreiben, ist die Verfügbarkeit von Lambdas in Kombination mit den von der Standardbibliothek bereitgestellten Algorithmen.
Ich benutze diese jetzt und es ist unglaublich, wie oft Sie einfach sagen, was Sie tun möchten, indem Sie count_if (), for_each () oder andere Algorithmen verwenden, anstatt die verdammten Schleifen erneut schreiben zu müssen.
Sobald Sie einen C ++ 11-Compiler mit einer vollständigen C ++ 11-Standardbibliothek verwenden, haben Sie keine gute Entschuldigung mehr, keine Standardalgorithmen zum Erstellen Ihrer zu verwenden . Lambda töte es einfach.
Warum?
In der Praxis (nachdem ich diese Art des Schreibens von Algorithmen selbst verwendet habe) fühlt es sich viel einfacher an, etwas zu lesen, das aus einfachen Wörtern besteht, die bedeuten, was getan wird, als mit einigen Schleifen, die Sie entschlüsseln müssen, um die Bedeutung zu kennen. Das automatische Ableiten von Lambda-Argumenten würde jedoch viel dazu beitragen, die Syntax leichter mit einer Raw-Schleife vergleichbar zu machen.
Grundsätzlich sind Lesealgorithmen, die mit Standardalgorithmen erstellt wurden, viel einfacher als Wörter, die die Implementierungsdetails der Schleifen verbergen.
Ich vermute, dass nur übergeordnete Algorithmen berücksichtigt werden müssen, da wir Algorithmen auf niedrigerer Ebene haben, auf denen wir aufbauen können.
quelle
for_each
ein Lambda besser ist als die äquivalente bereichsbasierte for-Schleife, mit dem Inhalt des Lambda in der Schleife. Der Code sieht mehr oder weniger gleich aus, aber das Lambda führt eine zusätzliche Interpunktion ein. Sie können Äquivalente von Dingen verwendenboost::irange
, um sie auf mehr Schleifen anzuwenden als nur auf solche, die offensichtlich Iteratoren verwenden. Darüber hinaus bietet die bereichsbasierte for-Schleife eine größere Flexibilität, da Sie bei Bedarf (nachreturn
oder nachbreak
) vorzeitig beenden können , währendfor_each
Sie mit werfen müssen.for
macht die Verfügbarkeit von Range-Based die üblicheit = c.begin(), const end = c.end(); it != end; ++it
Redewendung ungültig.for_each
Algorithmus gegenüber dem für die Schleife basierenden Bereich ist, dass Sie nichtbreak
oder könnenreturn
. Das heißt, wenn Sie sehen, dassfor_each
Sie sofort wissen, ohne auf den Körper zu schauen, dass es keine solche Schwierigkeit gibt.std::for_each(v.begin(), v.end(), [](int &i) { ++i; });
mitfor (auto &i : v) { ++i; }
. Ich akzeptiere, dass Flexibilität zweischneidig ist (goto
ist sehr flexibel, das ist das Problem). Ich glaube nicht , dass die Einschränkung von nicht verwenden zu können ,break
in derfor_each
Version kompensiert die zusätzliche Ausführlichkeit es verlangt - Nutzerfor_each
hier IMO tatsächliche Lesbarkeit und Komfort für eine Art theoretischer Vorstellung opfern , dass dasfor_each
ist im Prinzip klarer und konzeptuell einfacher. In der Praxis ist es nicht klarer oder einfacher.Sie müssen
swap
weniger häufig benutzerdefinierte Versionen implementieren . In C ++ 03swap
ist häufig ein effizientes Nicht-Werfen erforderlich, um kostspielige und werfende Kopien zu vermeiden. Dastd::swap
zwei Kopien verwendet werden, muss diesswap
häufig angepasst werden. In C ++std::swap
Anwendungenmove
, und so verschiebt sich der Fokus auf die Implementierung effizienter und nicht werfen bewegen Bauer und bewegen Zuweisungsoperatoren. Da für diese der Standard oft in Ordnung ist, ist dies viel weniger Arbeit als in C ++ 03.Im Allgemeinen ist es schwer vorherzusagen, welche Redewendungen verwendet werden, da sie durch Erfahrung entstehen. Wir können ein "Effective C ++ 11" vielleicht nächstes Jahr und einen "C ++ 11 Coding Standards" erst in drei Jahren erwarten, da die notwendige Erfahrung noch nicht vorhanden ist.
quelle
Ich kenne den Namen nicht, aber C ++ 03-Code verwendete häufig das folgende Konstrukt als Ersatz für fehlende Verschiebungszuweisungen:
Dies verhinderte jegliches Kopieren aufgrund von Kopierentfernung in Kombination mit dem
swap
Obigen.quelle
map
trotzdem konstruieren . Die Technik, die Sie zeigen, ist nützlich, wenn siemap
bereits vorhanden ist, anstatt nur konstruiert zu werden. Das Beispiel wäre besser ohne den Kommentar "billiger Standardkonstruktor" und mit "// ..." zwischen dieser Konstruktion und dem TauschAls ich bemerkte, dass ein Compiler, der den C ++ 11-Standard verwendet, den folgenden Code nicht mehr fehlerhaft macht:
für angeblich mit Operator >> begann ich zu tanzen. In den früheren Versionen müsste man tun
Um die Sache noch schlimmer zu machen, wenn Sie dies jemals debuggen mussten, wissen Sie, wie schrecklich die Fehlermeldungen sind, die daraus entstehen.
Ich weiß jedoch nicht, ob dies für Sie "offensichtlich" war.
quelle
Die Rückgabe nach Wert ist kein Problem mehr. Mit der Bewegungssemantik und / oder der Optimierung des Rückgabewerts (compilerabhängig) sind Codierungsfunktionen natürlicher, ohne Overhead oder Kosten (meistens).
quelle