Ich habe gelesen, dass wir in C ++ 17 Variablen in solchen if
Anweisungen initialisieren können
if (int length = 2; length == 2)
//execute something
Anstatt
int length = 2;
if (length == 2)
//do something
Obwohl es kürzer ist, beeinträchtigt es die Lesbarkeit des Codes (insbesondere für Leute, die diese neue Funktion nicht kennen), was meiner Meinung nach eine schlechte Codierungspraxis für die Entwicklung großer Software ist.
Gibt es einen anderen Vorteil bei der Verwendung dieser Funktion als die Verkürzung des Codes?
if (int length = 2; length == 2)
ist vielleicht überraschend, dass Sie es das erste Mal sehen, aber es ist nichts Komplexes, das man nicht verstehen konnte, so dass es bereits beim zweiten Mal keine große Überraschung mehr sein wird und Dinge in dem Bereich deklariert werden, in den sie gehören einer der Hauptfaktoren, die zur Lesbarkeit beitragen. Imho Ihre Prämisse ist falsch;)Antworten:
Es beschränkt den Umfang
length
auf dasif
Allein. Sie erhalten also die gleichen Vorteile, die wir ursprünglich hatten, als wir schreiben durftenfor(int i = 0; i < ... ; ++i) { // ... }
Anstelle der Variablen undicht
int i; for(i = 0; i < ... ; ++i) { // ... }
Kurzlebige Variablen sind aus mehreren Gründen besser. Aber um ein paar zu nennen:
Je kürzer etwas lebt, desto weniger Dinge müssen Sie beim Lesen nicht verwandter Codezeilen beachten. Wenn
i
es außerhalb der Schleife oderif
Anweisung nicht existiert , müssen wir uns nicht um den Wert außerhalb dieser Schleife kümmern. Wir müssen uns auch keine Sorgen machen, dass sein Wert mit anderen Teilen des Programms interagiert, die außerhalb des beabsichtigten Bereichs liegen (was passieren kann, wenni
oben in einer anderen Schleife wiederverwendet wird). Es erleichtert das Verfolgen und Überlegen von Code.Wenn die Variable eine Ressource enthält, wird diese Ressource jetzt für den kürzestmöglichen Zeitraum gespeichert. Und das ohne überflüssige geschweifte Klammern. Es wird auch klargestellt, dass die Ressource nur mit der Ressource zusammenhängt
if
. Betrachten Sie dies als ein motivierendes Beispielif(std::lock_guard _(mtx); guarded_thing.is_ready()) { }
Wenn Ihre Kollegen die Funktion nicht kennen, bringen Sie sie bei! Programmierer zu beschwichtigen, die nicht lernen möchten, ist eine schlechte Ausrede, um Funktionen zu vermeiden.
quelle
if (auto p = ptr.lock(); p && p->foo()) bar(*p);
{int i = 2; if (i == 2) {...}}
" (Beachten Sie den zusätzlichen Umfang.)Sie reduzieren den variablen Bereich. Dies ist sinnvoll und erhöht die Lesbarkeit, da dadurch die Lokalität der Bezeichner gestärkt wird, über die Sie nachdenken müssen. Ich bin damit einverstanden, dass lange init-Anweisungen in
if
Anweisungen vermieden werden sollten, aber für kurze Dinge ist es in Ordnung.Beachten Sie, dass Sie das Ergebnis bereits in Pre-C ++ 17 initialisieren und verzweigen können:
int *get(); // returns nullptr under some condition if (int *ptr = get()) doStuff();
Dies hängt von der persönlichen Meinung ab, aber Sie können eine explizite Bedingung als besser lesbar betrachten:
if (int *ptr = get(); ptr != nullptr) doStuff();
Außerdem ist es gefährlich, gegen die Lesbarkeit eines Features zu argumentieren, indem man sich auf die Tatsache bezieht, dass die Leute nicht daran gewöhnt sind. Die Leute waren irgendwann nicht mehr an kluge Zeiger gewöhnt, aber wir sind uns heute alle einig (ich denke), dass es gut ist, dass sie da sind.
quelle
if (auto p =get ())
da der Operator bool definiert istDie neue Form der if-Anweisung hat viele Verwendungszwecke.
Öffnen Sie den Standardvorschlag für die If-Anweisung mit dem Initialisierer
Zusammenfassend vereinfacht diese Anweisung gängige Codemuster und hilft Benutzern, die Bereiche eng zu halten.
Ich hoffe, es hilft!
quelle
Um den Umfang der Variablen zu minimieren, gibt es eine Redewendung, die eine Ressource nur dann definiert, wenn sie bei der Erstellung gültig ist (z. B. Dateistreamobjekte ):
if(auto file = std::ifstream("filename")) { // use file here } else { // complain about errors here } // The identifier `file` does not pollute the wider scope
Manchmal möchten Sie in der Lage sein, die Logik dieses Tests umzukehren, um den Fehler zur Primärklausel und die gültige Ressource zur
else
Klausel zu machen. Dies war bisher nicht möglich. Aber jetzt können wir tun:if(auto file = std::ifstream("filename"); !file) { // complain about errors here } else { // use file here }
Ein Beispiel könnte eine Ausnahme auslösen:
if(auto file = std::ifstream(filename); !file) throw std::runtime_error(std::strerror(errno)); else { // use file here }
Einige Leute codieren gerne so, dass eine Funktion bei einem Fehler frühzeitig abgebrochen wird und ansonsten fortschreitet. Diese Redewendung stellt die Abbruchlogik physisch über die Fortsetzungslogik, die manche Menschen vielleicht natürlicher finden.
quelle
Es ist besonders nützlich für logische Ereignisse. Betrachten Sie dieses Beispiel:
char op = '-'; if (op != '-' && op != '+' && op != '*' && op != '/') { std::cerr << "bad stuff\n"; }
Scheint etwas rau. Wenn Sie
OR, AND
mit Negationen nicht sehr vertraut sind , müssen Sie möglicherweise innehalten und über diese Logik nachdenken - die im Allgemeinen ein schlechtes Design ist. Mit demif-initialization
können Sie Ausdruckskraft hinzufügen.char op = '-'; if (bool op_valid = (op == '-') || (op == '+') || (op == '*') || (op == '/'); !op_valid) { std::cerr << "bad stuff\n"; }
Die benannte Variable kann auch innerhalb der wiederverwendet werden
if
. Z.B:if (double distance = std::sqrt(a * a + b * b); distance < 0.5){ std::cerr << distance << " is too small\n"; }
Dies ist großartig, insbesondere angesichts der Tatsache, dass die Variable einen Gültigkeitsbereich hat und daher den Speicherplatz danach nicht verschmutzt.
quelle
Dies ist eine Erweiterung einer vorhandenen Funktion, die meiner Erfahrung nach die Lesbarkeit verbessert.
if (auto* ptr = get_something()) { }
Hier erstellen wir beide die Variable
ptr
und testen, ob sie nicht null ist. Der Geltungsbereich vonptr
ist auf den Gültigkeitsbereich beschränkt. Es ist viel einfacher, sich davon zu überzeugen, dass jede Verwendungptr
gültig ist.Aber was ist, wenn wir über etwas sprechen, das sich nicht auf
bool
diese Weise umwandelt ?if (auto itr = find(bob)) { }
Das geht nicht Aber mit dieser neuen Funktion können wir:
if (auto itr = find(bob); itr != end()) { }
Fügen Sie eine Klausel hinzu, die besagt, wann diese Initialisierung gültig ist.
Im Wesentlichen erhalten wir eine Reihe von Token, die bedeuten: "Initialisieren Sie einen Ausdruck, und wenn er gültig ist, führen Sie einen Code aus. Wenn er nicht gültig ist, verwerfen Sie ihn."
Seit C ++ 98 ist es idiomatisch, den Zeigertest-Trick auszuführen. Sobald Sie das angenommen haben, ist diese Erweiterung natürlich.
quelle