Dies ist ein Follow-up zu meinem Frage von gestern . Ich habe Scott Meyers 'Warnung vor Schreibcode in meinem Kopf. Ich mag die Idee im Prinzip, Standardalgorithmen zu verwenden, um auf die Schlüssel oder Werte einer std :: map zuzugreifen, aber die erforderliche Syntax ist ein bisschen barock IMHO. Nehmen wir an, ich möchte alle Schlüssel einer Karte auf einen Vektor ausgeben. Gegeben folgende Erklärungen,
%Vor%Welcher Code ist wartbarer (d. h. möglicherweise weniger verwirrend)?
Option # 1:
%Vor%Option # 2:
%Vor%Option 1 ist mehr Standard Bibliothek-ish, aber ich muss es geistig zerlegen, um zu verstehen, was vor sich geht. Option 2 scheint auf Kosten einer möglichen kleinen Laufzeitstrafe leichter zu lesen. Ich habe keine Probleme mit der CPU-Zeit, also lehne ich mich Richtung Option 2 an. Stimmen Sie zu? Gibt es eine dritte Option, die ich in Betracht ziehen sollte?
P.S. Im Laufe des Schreibens dieser Frage kam ich zu dem Schluss, dass der beste Weg (für mein Projekt), die Schlüssel einer std :: map zu lesen, darin besteht, sie in einem Seitencontainer abzulegen und darüber zu iterieren. Die Frage der Wartbarkeit steht jedoch noch.
Klarheit schlägt immer schlauer. Mach was du später lesen kannst.
Sie denken nicht, dass der Standardcode etwas stumpf ist. Der nächste C ++ - Standard wird Lambda-Funktionen einführen, damit Sie mit den Standardalgorithmen besser lesbaren Code schreiben können.
Die erste ist genauso lesbar und wartbar wie die zweite - if Sie wissen, was bind
tut. Ich arbeite lange genug mit Boost :: Bind (im Wesentlichen identisch mit std::tr1::bind
), damit ich keine Probleme damit habe.
Sobald TR1 Teil des offiziellen Standards wird, können Sie sicher davon ausgehen, dass jeder kompetente C ++ - Programmierer es verstehen wird. Bis dahin könnte es einige Schwierigkeiten bereiten, aber ich denke immer langfristig an die langfristige.
Sie haben using namespace std::tr1::placeholders
: P
Um ehrlich zu sein, ist der letztere Code für einfache Algorithmen wahrscheinlich leichter zu pflegen. Aber ich tendiere tatsächlich zu ersterem (besonders, wenn C ++ 1x uns Lambdas gibt!), Weil es einen funktionalen Stil der Programmierung betont, den ich persönlich dem imperativen Stil der Verwendung einer Schleife vorziehe.
Es ist wirklich eine andere Schlaganfall-Sache; Standardalgorithmen sind am nützlichsten, wenn sie entweder komplex oder generisch sind, und dies auch nicht.
So wird es bei Lambdas aussehen:
%Vor%Und eigentlich gibt es einen anderen Ansatz, den ich bevorzugen würde, aber für seine Ausführlichkeit:
%Vor%Und mit lambdas (das ist wahrscheinlich im Großen und Ganzen die sauberste und eindeutigste aller Optionen):
%Vor%Ich sage, gehen Sie für 2)
Um die Leistung zu verbessern, könnten Sie m.end()
aus der Schleife herausholen und den Platz im Vektor reservieren.
Kann nicht auf C ++ 0x und die bereichsbasierte for-Schleife warten; das würde deine Schleife noch besser machen.
Gehen Sie zu Option # 1, siehe Scott Meyers, Effektive STL Punkt # 43, Seite 181.
Als ich gestern Ihre Frage anschaute, war es nicht die Bindung (die ich oft verwende), die mich zwang, zweimal zu schauen, um den Code zu verstehen, aber map :: value_type :: first, zu dem ich keine Gelegenheit hatte sehr oft benutzen. Während ich zustimme, dass "Klarheit immer schlauer ist", ist Vertrautheit vor Klarheit erforderlich und Sie werden sich nicht mit Stilen vertraut machen, die Sie nicht verwenden ...
Ich würde auch sagen, dass Option 2 zwar den Zweck besser versteht, einen Fehler jedoch leichter verbergen würde (jeder Fehler in Option 1 ist wahrscheinlicher zur Kompilierungszeit sichtbar).
Ich würde für Option # 3 gehen:
%Vor%Dies hat die Vorteile, dass es:
ist kürzer
verwendet eine benannte Funktion, um die Schlüssel
ist (potenziell) effizienter (weil boost::push_back
reserve()
auf v
aufrufen kann)
und erfordert nicht das redundante v.begin()
, v.end()
-Paar.
Jeder andere Weg ist purer Wahnsinn.