Ich habe das neue auto
Schlüsselwort verwendet, das im C ++ 11-Standard für komplizierte Vorlagen verfügbar ist. Ich glaube, es wurde dafür entwickelt. Aber ich benutze es auch für Dinge wie:
auto foo = std::make_shared<Foo>();
Und skeptischer für:
auto foo = bla(); // where bla() return a shared_ptr<Foo>
Ich habe nicht viel Diskussion zu diesem Thema gesehen. Es scheint, dass auto
dies überbeansprucht werden könnte, da ein Typ häufig eine Form der Dokumentation und Überprüfung der geistigen Gesundheit ist. Wo ziehen Sie die Grenze bei der Verwendung auto
und was sind die empfohlenen Anwendungsfälle für diese neue Funktion?
Zur Verdeutlichung: Ich bitte nicht um eine philosophische Meinung; Ich bitte das Standardkomitee um die beabsichtigte Verwendung dieses Schlüsselworts, möglicherweise mit Kommentaren dazu, wie diese beabsichtigte Verwendung in der Praxis umgesetzt wird.
Randnotiz: Diese Frage wurde zu SE.Programmers und dann zurück zu Stack Overflow verschoben. Eine Diskussion darüber finden Sie in dieser Meta-Frage .
auto
Schlüsselwort wirklich verwendet haben , wissen Sie, wie es verwendet werden soll . Das ist es, was ich als jemand, der neu in dieser Funktion ist, frage, wie ich sie verwenden soll.var
(das heißt, als die Leute über die Idee hinwegkamen, dass es doch kein dynamisches Tippen war). Wenn Sie möchten, können Sie mit dieser Frage beginnen und die entsprechenden Fragen durchgehen.auto foo = bla();
"schlecht" zu nennen ist eindeutig eine Meinung, keine Tatsache, die diese Frage stellt und eine Diskussion beantwortet, die sie für Programmers SE relevant macht, was genau das ist, was die engen Abstimmungen anzeigen. / AchselzuckenAntworten:
Ich denke, dass man das
auto
Schlüsselwort immer dann verwenden sollte, wenn es schwierig ist zu sagen, wie man den Typ auf den ersten Blick schreibt, aber der Typ der rechten Seite eines Ausdrucks ist offensichtlich. Zum Beispiel mit:um den zusammengesetzten Schlüsseltyp einzugeben
boost::multi_index
, obwohl Sie wissen, dass dies der Fall istint
. Sie können nicht einfach schreiben,int
weil es in Zukunft geändert werden könnte. Ich würdeauto
in diesem Fall schreiben .Wenn das
auto
Schlüsselwort in einem bestimmten Fall die Lesbarkeit verbessert, verwenden Sie es. Sie können schreiben,auto
wenn dem Leser klar ist, welchen Typ erauto
darstellt.Hier sind einige Beispiele:
quelle
bla()
Sie ihm gebenfoo
.Verwenden
auto
Sie es überall, wo Sie können - insbesondere,const auto
damit Nebenwirkungen weniger bedenklich sind. Sie müssen sich nur in den offensichtlichen Fällen um Typen kümmern, diese werden jedoch für Sie statisch überprüft, und Sie können Wiederholungen vermeiden. Wo diesauto
nicht möglich ist, können Siedecltype
Typen semantisch als Verträge ausdrücken, die auf Ausdrücken basieren. Ihr Code wird anders aussehen, aber es wird eine positive Änderung sein.quelle
auto&&
in komplexen Situationen edmundv.home.xs4all.nl/blog/2014/01/28/…const auto&
oder esconst auto
sei denn, ich möchte explizit mutieren oder mich bewegen.auto str = std::string();
stattstd::string str;
?Einfach. Verwenden Sie es, wenn es Ihnen egal ist, um welchen Typ es sich handelt. Beispielsweise
Alles, was mich hier interessiert, ist, dass
i
alles in dem Container ist.Es ist ein bisschen wie typedefs.
Hier ist es mir egal, ob
h
und obw
es sich um Schwimmer oder Doppel handelt, nur dass sie für jeden Typ geeignet sind, um Höhen und Gewichte auszudrücken .Oder überlegen Sie
Hier ist mir nur wichtig, dass es ein geeigneter Iterator ist, der unterstützt
operator++()
, es ist in dieser Hinsicht wie das Tippen von Enten.Auch die Art der Lambdas kann nicht geschrieben werden, also
auto f = []...
ist es ein guter Stil. Die Alternative ist Casting,std::function
aber das bringt Overhead mit sich.Ich kann mir einen "Missbrauch" von nicht wirklich vorstellen
auto
. Das nächste, was ich mir vorstellen kann, ist, sich einer expliziten Konvertierung in einen signifikanten Typ zu berauben - aber Sie würden das nicht verwendenauto
, Sie würden ein Objekt des gewünschten Typs konstruieren.Wenn Sie Redundanz in Ihrem Code entfernen können , ohne Nebenwirkungen einzuführen, muss dies sinnvoll sein.
Gegenbeispiele (aus den Antworten eines anderen entlehnt):
Hier ist es uns egal, was der Typ ist, also sollten wir schreiben
Someclass i;
undfor(unsigned x = y;...
quelle
auto
.Tue es. Verwenden Sie es
auto
überall dort, wo es das Schreiben von Code erleichtert.Jede neue Funktion in einer beliebigen Sprache wird zumindest von einigen Programmierertypen überbeansprucht. Nur durch mäßige Überbeanspruchung durch einige erfahrene Programmierer (nicht durch Noobs) lernt der Rest der erfahrenen Programmierer die Grenzen der richtigen Verwendung. Extreme Überbeanspruchung ist normalerweise schlecht, kann aber gut sein, da eine solche Überbeanspruchung zu Verbesserungen der Funktion oder zu einer besseren Funktion führen kann, um sie zu ersetzen.
Aber wenn ich an Code mit mehr als ein paar Zeilen wie arbeiten würde
Wenn der Typ nullmal angegeben wird, möchte ich diese Zeilen möglicherweise so ändern, dass sie Typen enthalten. Das erste Beispiel ist großartig, da der Typ einmal angegeben wird und
auto
wir nicht zweimal unordentliche Vorlagen schreiben müssen. Hurra für C ++++. Das explizite Null-malige Anzeigen des Typs, wenn er in einer nahe gelegenen Zeile nicht leicht sichtbar ist, macht mich nervös, zumindest in C ++ und seinen unmittelbaren Nachfolgern. Für andere Sprachen, die auf einer höheren Ebene mit mehr Abstraktion, Polymorphismus und Generizität arbeiten sollen, ist dies in Ordnung.quelle
Bei C ++ und darüber hinaus 2012 gab es im Ask Us Anything- Panel einen fantastischen Austausch zwischen Andrei Alexandrescu, Scott Meyers und Herb Sutter, in dem darüber gesprochen wurde, wann und wann nicht
auto
. Fahren Sie mit Minute 25:03 fort, um eine 4-minütige Diskussion zu führen. Alle drei Lautsprecher bieten hervorragende Punkte, die beachtet werden sollten, wenn sie nicht verwendet werdenauto
.Ich ermutige die Leute sehr, zu ihrem eigenen Schluss zu kommen, aber mein Mitnehmen war, es überall zu verwenden
auto
, es sei denn :Die liberale Verwendung von
explicit
hilft, die Sorge um letztere zu verringern, was dazu beiträgt, die Zeit zu minimieren, die erstere ein Problem darstellen.Formulieren Sie neu, was Herb gesagt hat: "Wenn Sie nicht X, Y und Z tun, verwenden Sie
auto
. Lernen Sie, was X, Y und Z sind, und gehen Sie weiter und verwenden Sieauto
überall anders."quelle
Ja, es kann zu Lasten der Lesbarkeit überbeansprucht werden. Ich schlage vor, es in Kontexten zu verwenden, in denen genaue Typen lang oder unaussprechlich oder für die Lesbarkeit nicht wichtig sind und Variablen nur von kurzer Dauer sind. Zum Beispiel ist der Iteratortyp normalerweise lang und nicht wichtig, also
auto
würde es funktionieren:auto
Hier schadet die Lesbarkeit nicht.Ein weiteres Beispiel ist der Parser-Regeltyp, der lang und kompliziert sein kann. Vergleichen Sie:
mit
Wenn der Typ bekannt und einfach ist, ist es viel besser, wenn ausdrücklich angegeben wird:
eher, als
quelle
begin()
undend()
oder Ihre Schrittgröße eine andere als eine ist oder Sie den Container während der Schleife ändern, hilft Ihnen die bereichsbasierte for-Anweisung nicht weiter.r_and_t<r_and_t<r_char_t<char>&, r_char_t<char>&>, r_char_t<char>&>
tut?space
ist, und danach suchen. Das sind sowieso die nützlicheren Informationen ... schließlich geht es nicht um "Welcher Typ ist diese neue Variable", sondern um "Was bedeutetspace & space & space
das?". Der eigentliche Typ des Ausdrucks ist nur Rauschen.auto
kann in Kombination mit Ausdrucksvorlagen, die häufig von linearen Algebra-Bibliotheken wie Eigen oder OpenCV verwendet werden, sehr gefährlich sein.Fehler, die durch diese Art von Fehlern verursacht werden, sind ein großes Problem beim Debuggen. Eine mögliche Abhilfe besteht darin, das Ergebnis explizit in den erwarteten Typ umzuwandeln, wenn Sie Auto für den Deklarationsstil von links nach rechts verwenden möchten.
quelle
A*B
Ausdruck in eineauto
Variable oder in etwas anderes kopiert wird oder nicht , ist das von Ihnen beschriebene Verhalten weiterhin vorhanden.auto
.diag(A * B)
müssen keine Zyklen für die Berechnung der nicht diagonalen Elemente verschwendet werden.Ich benutze
auto
ohne Einschränkung und hatte kein Problem. Ich benutze es sogar manchmal für einfache Typen wieint
. Dies macht C ++ für mich zu einer höheren Sprache und ermöglicht das Deklarieren von Variablen in C ++ wie in Python. Nach dem Schreiben von Python-Code schreibe ich manchmal sogar zanstatt
Dies ist ein Fall, in dem ich sagen würde, dass es sich um einen Missbrauch des
auto
Schlüsselworts handelt.Oft macht es mir nichts aus, was der genaue Typ des Objekts ist, ich interessiere mich mehr für seine Funktionalität, und da Funktionsnamen im Allgemeinen etwas über die Objekte aussagen, die sie zurückgeben,
auto
tut das nicht weh: z. B.auto s = mycollection.size()
kann ich mir vorstellen, dass diess
der Fall sein wird Eine Art Ganzzahl, und in dem seltenen Fall, in dem mir der genaue Typ am Herzen liegt, überprüfen wir dann den Funktionsprototyp (ich meine, ich muss lieber prüfen, wann ich die Informationen benötige, als a priori, wenn Code geschrieben wird) für den Fall, dass es eines Tages nützlich wäre, wie inint_type s = mycollection.size()
).Zu diesem Beispiel aus der akzeptierten Antwort:
In meinem Code verwende ich
auto
in diesem Fall immer noch, und wenn ich nichtx
signiert werden möchte , verwende ich eine Dienstprogrammfunktion namens saymake_unsigned
, die meine Bedenken klar zum Ausdruck bringt:Haftungsausschluss: Ich beschreibe nur meine Verwendung, ich bin nicht kompetent, Ratschläge zu geben!
quelle
auto i = MyClass()
.as_unsigned
wird dort oder sogar empfohlenauto w = widget{};
.Einer der wichtigsten Problem mit C ++ Programm ist es Ihnen die verwenden können nicht initialisierten Variablen . Dies führt uns zu einem unangenehmen, nicht deterministischen Programmverhalten. Es sollte beachtet werden, dass der moderne Compiler jetzt entsprechende / Meldungswarnmeldungen ausgibt, wenn das Programm müde wird, es zu verwenden.
Um dies zu veranschaulichen, betrachten Sie das folgende c ++ - Programm:
Wenn ich dieses Programm mit einem modernen Compiler (GCC) kompiliere, wird eine Warnung ausgegeben. Eine solche Warnung ist möglicherweise nicht sehr offensichtlich, wenn wir mit dem wirklich komplexen Produktionscode arbeiten.
================================================== ============================== Wenn wir nun unser Programm ändern, das auto verwendet , erhalten wir beim Kompilieren Folgendes:
Mit auto ist es nicht möglich, die nicht initialisierte Variable zu verwenden. Dies ist ein großer Vorteil, den wir (kostenlos) erhalten können, wenn wir Auto verwenden .
Dieses Konzept und andere großartige moderne C ++ - Konzepte werden vom C ++ - Experten Herb Shutter in seinem CppCon14- Vortrag erklärt:
Zurück zu den Grundlagen! Grundlagen des modernen C ++ - Stils
quelle
auto
.auto
- aber Sie brauchen es nicht, um dieses Problem zu vermeiden.Eine Gefahr, die ich festgestellt habe, sind Referenzen. z.B
Das Problem ist, dass another_ref in diesem Fall keine Referenz ist. Es ist MyBigObject anstelle von MyBigObject &. Am Ende kopieren Sie ein großes Objekt, ohne es zu merken.
Wenn Sie eine Referenz direkt von einer Methode erhalten, denken Sie möglicherweise nicht darüber nach, was sie tatsächlich ist.
Sie würden "auto &" oder "const auto &" benötigen
quelle
Verwenden
auto
Sie diese Option, wenn ein Typ abgeleitet werden soll. Wenn Sie etwas haben, von dem Sie wissen, dass es eine Ganzzahl ist, oder wenn Sie wissen, dass es eine Zeichenfolge ist, verwenden Sie einfach int / std :: string usw. Ich würde mir keine Sorgen darüber machen, eine Sprachfunktion zu "überbeanspruchen", es sei denn, sie wird lächerlich. oder verschleiert Code.Das ist sowieso meine Meinung.
quelle
auto
Das Schlüsselwort kann nur für lokale Variablen verwendet werden, nicht für Argumente oder Klassen- / Strukturelemente. Es ist also sicher und praktikabel, sie überall dort einzusetzen, wo Sie möchten. Ich benutze sie oft. Der Typ wird zur Kompilierungszeit abgeleitet, der Debugger zeigt den Typ beim Debuggen an,sizeof
meldet ihn korrekt,decltype
würde den richtigen Typ angeben - es gibt keinen Schaden. Ich zähle nieauto
als überstrapaziert!quelle
TL; DR: Siehe Faustregel unten.
Die akzeptierte Antwort schlägt die folgende Faustregel vor:
Aber ich würde sagen, das ist zu restriktiv. Manchmal interessieren mich die Typen nicht, da die Aussage informativ genug ist, ohne dass ich mir die Zeit nehme, den Typ herauszufinden. Was meine ich damit? Betrachten Sie das Beispiel, das in einigen Antworten aufgetaucht ist:
Was macht dies zu einem Beispiel für Missbrauch
auto
? Ist es meine Unkenntnis desf()
Rückgabetyps? Nun, es mag zwar helfen, wenn ich es wüsste, aber - das ist nicht mein Hauptanliegen. Was viel mehr ein Problem ist, ist dasx
undf()
sind ziemlich bedeutungslos. Wenn wir hätten:Stattdessen ist es mir normalerweise egal, ob der Rückgabetyp der Funktion offensichtlich ist oder nicht. Wenn ich die Anweisung lese, weiß ich, was ich tue, und ich weiß genug über die Semantik des Rückgabewerts, um nicht das Gefühl zu haben, dass ich auch seinen Typ kennen muss.
Meine Antwort lautet also: Verwenden Sie,
auto
wann immer der Compiler dies zulässt, es sei denn:Und auch:
auto
den konkreten Typ ersetzen .quelle
Eine meiner bitteren Erfahrungen mit
auto
ist die Verwendung mit Lambda-Ausdrücken :Eigentlich wird hier
i
der Funktionszeiger von aufgelöstint(*)()
. Dies ist nur eine einfachecout
, aber stellen Sie sich vor, welche Art von fehlerhaften Kompilierungs- / Laufzeitfehlern sie bei Verwendung verursachen könnentemplate
.Sie sollten solche Ausdrücke vermeiden
auto
und einen geeignetenreturn
Typ (oder einen kontrolliertendecltype()
) eingeben.Die korrekte Verwendung für das obige Beispiel wäre:
quelle
()
am Ende setzen möchte . Lambdas dienen als Funktionen, und daher kommt die Funktionszeigerkonvertierung. Wenn Sie es sofort anrufen möchten, warum überhaupt ein Lambda verwenden?auto i = 0;
funktioniert ziemlich gut.auto x = []() { /* .... whatever goes in here ... */ }()
besser ist alsauto x = /* .... whatever goes in here ... */;
dasselbe? Ich finde das ziemlich sinnlos, aus dem gleichen Grundauto x = 42 + y - 42
ist es sinnlos.