Ist es richtig, beim Erstellen lokaler Variablen (const) auto&
oder zu verwenden auto
?
z.B:
SomeClass object;
const auto result = object.SomeMethod();
oder const auto& result = object.SomeMethod();
Wobei SomeMethod () einen nicht primitiven Wert zurückgibt - möglicherweise einen anderen benutzerdefinierten Typ. const auto& result
Nach meinem Verständnis ist dies korrekt, da das von SomeMethod () zurückgegebene Ergebnis den Kopierkonstruktor für den zurückgegebenen Typ aufrufen würde. Bitte korrigieren Sie mich, wenn ich falsch liege.
Was ist mit primitiven Typen? Ich nehme an, const auto sum = 1 + 2;
ist richtig.
Gilt dies auch für Bereiche, die auf Schleifen basieren?
for(const auto& object : objects)
auto
(mit Ausnahme des besonderen Falls voninitializer_list
s) nicht in einem Vorlagenkontext abgeleitet), geben Sie dannauto
Abzug ein.Antworten:
auto
undauto &&
decken die meisten Fälle ab:Verwenden
auto
Sie diese Option, wenn Sie eine lokale Kopie benötigen. Dies wird niemals eine Referenz erzeugen. Der Kopierkonstruktor (oder Verschiebungskonstruktor) muss vorhanden sein, wird jedoch aufgrund der Optimierung der Kopierelision möglicherweise nicht aufgerufen .Verwenden
auto &&
Sie diese Option, wenn es Ihnen egal ist, ob das Objekt lokal ist oder nicht. Technisch gesehen erzeugt dies immer eine Referenz, aber wenn der Initialisierer ein temporärer ist (z. B. die Funktion wird nach Wert zurückgegeben), verhält er sich im Wesentlichen wie Ihr eigenes lokales Objekt.Außerdem
auto &&
garantiert nicht , dass das Objekt veränderbar sein wird, auch nicht . Wenn einconst
Objekt oder eine Referenz gegeben ist, wird daraus abgeleitetconst
. In Anbetracht des spezifischen Kontexts wird jedoch häufig von einer Modifizierbarkeit ausgegangen.auto &
undauto const &
sind etwas spezifischer:auto &
garantiert, dass Sie die Variable mit etwas anderem teilen. Es ist immer ein Hinweis und niemals auf eine vorübergehende.auto const &
ist wieauto &&
, bietet aber schreibgeschützten Zugriff.Es gibt keinen Unterschied.
Ja. Anwendung der oben genannten Grundsätze,
auto &&
diese Option, um Werte der Sequenz innerhalb der Schleife zu ändern und zu verwerfen. (Das heißt, es sei denn, der Container bietet eine schreibgeschützte Ansicht, z. B.std::initializer_list
in diesem Fall handelt es sich tatsächlich um eineauto const &
.)auto &
diese Option, um die Werte der Sequenz auf sinnvolle Weise zu ändern.auto const &
für Nur - Lese-Zugriff.auto
diese Option , um mit (veränderbaren) Kopien zu arbeiten.Sie erwähnen auch
auto const
ohne Referenz. Dies funktioniert, wird jedoch nicht häufig verwendet, da der schreibgeschützte Zugriff auf etwas, das Sie bereits besitzen, selten von Vorteil ist.quelle
auto&
scheint eine gute Wahl zu sein. Verwendenconst auto&
Sie diese Option jedoch, wenn Sie Konstanz hinzufügen möchten, die noch nicht vorhanden ist.auto&&
ist für die Weiterleitung, was meiner Meinung nach häufiger vorkommt als Sutter denkt. Beispielsweise möchten Sie möglicherweise einen Rückgabewert von speichernauto&&
und ihn dann an zwei Dinge "weiterleiten", z. B. std :: cout, um den Wert für das Debuggen anzuzeigen und ihn auch an eine andere Funktion zu übergeben. Ich habe Auto && öfter benutzt, wurde aber ein- oder zweimal von ihm gebissen, als es einige unerwartete Dinge tat. Ich wünschte, ich hätte mehr beachtet, was schief gelaufen ist!auto&&
ist ein fehlendes Sprachfeature verwendet, das sollte jeder Aussage erlaubt in kleinere Aussagen geteilt werden. Der fehlende Teil ist die Verlängerung der Lebensdauer… Ich habe mich sehr bemüht, dies zu beheben, aber niemand hat es bemerkt. Legen Sie nicht zu viel Wert auf Panditerie :)Ja, es ist richtig zu verwenden
auto
undauto&
für lokale Variablen. Wenn Sie den Rückgabetyp einer Funktion erhalten, ist die Verwendung ebenfalls korrektauto&
. Dies gilt auch für Bereiche, die auf Schleifen basieren.Allgemeine Regeln für die Verwendung
auto
sind:auto x
wann Sie mit Kopien arbeiten möchten.auto &x
wann Sie mit Originalelementen arbeiten möchten, und ändern Sie diese möglicherweise.auto const &x
wann Sie mit Originalelementen arbeiten möchten und diese nicht ändern möchten.Weitere Informationen zum automatischen Spezifizierer finden Sie hier .
quelle
auto
verwendet den gleichen Mechanismus der Typableitung wie Vorlagen. Die einzige mir bekannte Ausnahme sind Klammer-Init-Listen, die vonauto
as abgeleitetstd::initializer_list
, aber in einem Vorlagenkontext nicht abgeleitet werden.auto x = expression;
funktioniert, indem zuerst alle Referenz- und Lebenslaufqualifizierer vom Typ des Ausdrucks auf der rechten Seite entfernt und dann mit dem Typ abgeglichen werden. Zum Beispiel, wenn Sie
const int& f(){...}
dannauto x = f();
folgertx
wieint
, und nichtconst int&
.Die andere Form,
auto& x = expression
nicht abzustreifen die cv-Qualifizierer, also vor dem Beispiel verwendet wird ,
auto& x = f()
folgertx
wieconst int&
. Die anderen Kombinationen fügen nur Lebenslaufqualifizierer hinzu.Wenn Sie möchten, dass Ihr Typ immer mit cv-ref-Qualifizierern abgeleitet wird, verwenden Sie das berüchtigte
decltype(auto)
in C ++ 14, das diedecltype
Typabzugsregeln verwendet.Kurz gesagt, wenn Sie Kopien möchten, verwenden Sie
auto
, wenn Sie Referenzen möchten, verwenden Sieauto&
. Verwendenconst
Sie, wann immer Sie zusätzlicheconst
-ness wünschen .BEARBEITEN Es gibt einen zusätzlichen Anwendungsfall,
auto&& x = expression;
Dabei werden die Regeln zum Reduzieren von Referenzen verwendet, wie im Fall der Weiterleitung von Referenzen im Vorlagencode. Wenn
expression
es sich um einen Wert handelt,x
handelt es sich um eine Wertreferenz mit den Lebenslaufqualifizierern vonexpression
. Wennexpression
es sich um einen rWert handelt,x
handelt es sich um eine rWert-Referenz.quelle
rvalues
. Gibt es eine einfache Möglichkeit zum Testen? Und wie können Sie einen Lebenslauf-qualifizierten Wert haben? Bei Funktionsrückgabe wird cv verworfen.auto && x = std::move< const int >( 5 );
werden deklariertint const && x
, obwohl sie selten verwendet werden.Ja. Das Auto ist nichts anderes als ein vom Compiler abgeleiteter Typ. Verwenden Sie daher Referenzen, bei denen Sie normalerweise Referenzen verwenden würden, und lokale (automatische) Kopien, bei denen Sie normalerweise lokale Kopien verwenden würden. Ob eine Referenz verwendet werden soll oder nicht, ist unabhängig vom Typabzug.
Legal? Ja, mit der const. Beste Übung? Wahrscheinlich nicht, nein. Zumindest nicht mit C ++ 11. Insbesondere nicht, wenn der von SomeMethod () zurückgegebene Wert bereits temporär ist. Sie möchten mehr über die C ++ 11-Verschiebungssemantik, die Kopierelision und die Optimierung von Rückgabewerten erfahren: https://juanchopanzacpp.wordpress.com/2014/05/11/want-speed-dont-always-pass-by- Wert/
http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=199
https://isocpp.org/wiki/faq/ctors#return-by-value-optimization
Ja, das ist in Ordnung.
Ja, das ist auch gut so. Ich schreibe diese Art von Code die ganze Zeit bei der Arbeit.
quelle