Wie viel ist zu viel mit dem automatischen Schlüsselwort C ++ 11?

218

Ich habe das neue autoSchlü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 autodies ü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 autound 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 .

Alan Turing
quelle
Dies ist jedoch eine Q & A-Site, keine Diskussionsseite. Sie haben eine sehr sehr allgemeine Frage gestellt, und ich bezweifle, dass Ihnen jemand etwas anderes als eine höchst subjektive Frage geben kann. (deshalb -1)
TravisG
15
@heishe, ich habe eine Klarstellung hinzugefügt. Wenn Sie die Frage sehr allgemein lesen, scheint sie eine subjektive Meinung zu sein, aber wenn Sie das autoSchlü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.
Alan Turing
13
Ich habe diese Diskussion überall gesehen, als C # eingeführt wurde 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.
R. Martinho Fernandes
2
@Lex: Entweder ist etwas legal oder nicht; etwas "Schlechtes" zu nennen, das legal ist, ist per Definition subjektiv. Das heißt, 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. / Achselzucken
ildjarn
3
Herb Sutter Ansicht zu diesem Thema: herbsutter.com/2013/06/13/…
Rafak

Antworten:

131

Ich denke, dass man das autoSchlü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:

my_multi_type::nth_index<2>::type::key_type::composite_key_type::
    key_extractor_tuple::tail_type::head_type::result_type

um den zusammengesetzten Schlüsseltyp einzugeben boost::multi_index, obwohl Sie wissen, dass dies der Fall ist int. Sie können nicht einfach schreiben, intweil es in Zukunft geändert werden könnte. Ich würde autoin diesem Fall schreiben .

Wenn das autoSchlüsselwort in einem bestimmten Fall die Lesbarkeit verbessert, verwenden Sie es. Sie können schreiben, autowenn dem Leser klar ist, welchen Typ er autodarstellt.

Hier sind einige Beispiele:

auto foo = std::make_shared<Foo>();   // obvious
auto foo = bla();                     // unclear. don't know which type `foo` has

const size_t max_size = 100;
for ( auto x = max_size; x > 0; --x ) // unclear. could lead to the errors
                                      // since max_size is unsigned

std::vector<some_class> v;
for ( auto it = v.begin(); it != v.end(); ++it )
                                      // ok, since I know that `it` has an iterator type
                                      // (don't really care which one in this context)
Kirill V. Lyadvinsky
quelle
18
Das scheint keine sehr gute Empfehlung zu sein. Wie oft kennen Sie den Objekttyp nicht? (Außerhalb von Vorlagen.) Und wenn Sie nicht wissen, dass sie tippen, schauen Sie nach, seien Sie nicht faul und verwenden Sie auto.
Paul Manta
9
@Paul: Oft wissen Sie nur oder müssen nur den wichtigsten Teil des Typs kennen, z. B. dass es sich um einen Iterator handelt, aber Sie wissen nicht, ob es sich um einen Iterator von Vektoren oder einen Iterator von verknüpften handelt aufführen; In diesen Fällen möchten Sie wirklich keine Zeit und keinen Platz auf dem Bildschirm verbringen, um herauszufinden, wie die Typen aufgeschrieben werden.
Lie Ryan
45
Unabhängig davon, ob C ++ diehards es mögen oder nicht, C ++ 0x wird Leute anziehen, die C ++ niemals benutzt hätten. Und diese werden überall Auto verwenden.
Prof. Falken
6
@ R.MartinhoFernandes - nein, das einzige, was klar ist, ist, dass Sie alles zurückgeben , wasbla() Sie ihm geben foo.
Luis Machuca
8
@LuisMachuca Meine Antwort war eine ironische Art zu sagen, dass es unehrlich ist, ein Lehrbuchbeispiel für eine schlechte Benennung von Variablen und Funktionen zu geben und die mangelnde Lesbarkeit der Typinferenz zuzuschreiben.
R. Martinho Fernandes
62

Verwenden autoSie es überall, wo Sie können - insbesondere, const autodamit 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 dies autonicht möglich ist, können Sie decltypeTypen semantisch als Verträge ausdrücken, die auf Ausdrücken basieren. Ihr Code wird anders aussehen, aber es wird eine positive Änderung sein.

Jon Purdy
quelle
12
Ich würde besonders sagen 'const auto &'
Viktor Sehr
2
Bessere Verwendung auto&&in komplexen Situationen edmundv.home.xs4all.nl/blog/2014/01/28/…
KindDragon
2
@KindDragon: Das ist eine gute Faustregel, aber ich bevorzuge die Verwendung const auto&oder es const autosei denn, ich möchte explizit mutieren oder mich bewegen.
Jon Purdy
" Verwenden Sie Auto überall, wo Sie können ". Bedeutet dies , ich schreiben sollte auto str = std::string();statt std::string str;?
Calmarius
4
Wenn Sie überall Auto verwenden, ist Ihr Code weniger lesbar und schwerer zu debuggen, da Sie die Typen beim Lesen des Codes selbst ableiten müssen.
SubMachine
52

Einfach. Verwenden Sie es, wenn es Ihnen egal ist, um welchen Typ es sich handelt. Beispielsweise

for (const auto & i : some_container) {
   ...

Alles, was mich hier interessiert, ist, dass ialles in dem Container ist.

Es ist ein bisschen wie typedefs.

typedef float Height;
typedef double Weight;
//....
Height h;
Weight w;

Hier ist es mir egal, ob hund ob wes 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

for (auto i = some_container .begin (); ...

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::functionaber 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 verwenden auto, 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):

auto i = SomeClass();
for (auto x = make_unsigned (y); ...)

Hier ist es uns egal, was der Typ ist, also sollten wir schreiben Someclass i;undfor(unsigned x = y;...

Spraff
quelle
1
Äh. Nicht so einfach. Es wird kompiliert und ausgeführt, und Sie haben sich gerade in den Fuß geschossen, wenn es sich bei den Elementen um nicht triviale Objekte handelt. Ihre Iteration ruft bei jedem Schritt der Iteration den Kopierkonstruktor und den Destruktor auf. Wenn Sie auto in einem bereichsbasierten Iterator blind verwenden, sollte es wahrscheinlich "for (const auto & item: some_container)" anstelle von "for (auto item: some_container)" sein.
Don Hatch
2
Nicht immer, aber ok, Sie möchten wahrscheinlich Referenzen. Na und? Das hat nichts damit zu tun auto.
Spraff
Ich verstehe deinen letzten Kommentar wirklich nicht. Ich habe versucht zu erklären, warum Ihre Strategie für mich nicht sehr gut aussieht und warum ich sie ablehne.
Don Hatch
5
Ich sage, ob Sie Referenzen verwenden oder nicht, ist orthogonal dazu, ob Sie Auto verwenden oder nicht. Ich werde es bearbeiten, um die Referenz hinzuzufügen, da dies zwar normalerweise der Fall ist, aber für das jeweilige Thema völlig irrelevant ist.
Spraff
43

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

auto foo = bla();

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 autowir 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.

DarenW
quelle
38

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 nichtauto . 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 werden auto.

Ich ermutige die Leute sehr, zu ihrem eigenen Schluss zu kommen, aber mein Mitnehmen war, es überall zu verwenden auto, es sei denn :

  1. Es schadet der Lesbarkeit
  2. Es gibt Bedenken hinsichtlich der automatischen Typkonvertierung (z. B. von Konstruktoren, Zuweisung, Vorlagenzwischen-Typen, implizite Konvertierung zwischen ganzzahligen Breiten).

Die liberale Verwendung von explicithilft, 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 Sie autoüberall anders."

Sean
quelle
4
Wahrscheinlich auch einen Link
Rob Starling
37

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 autowürde es funktionieren:

   for(auto i = container.begin(); i != container.end(); ++i);

auto Hier schadet die Lesbarkeit nicht.

Ein weiteres Beispiel ist der Parser-Regeltyp, der lang und kompliziert sein kann. Vergleichen Sie:

   auto spaces = space & space & space;

mit

r_and_t<r_and_t<r_char_t<char>&, r_char_t<char>&>, r_char_t<char>&> spaces = 
   space & space & space;

Wenn der Typ bekannt und einfach ist, ist es viel besser, wenn ausdrücklich angegeben wird:

int i = foo();

eher, als

auto i = foo();
Gene Bushuyev
quelle
2
Natürlich macht eine bereichsbasierte for-Schleife in der Sprache Ihr erstes Beispiel weniger aufregend. 8v)
Fred Larson
@Fred: Der Typ kann immer noch umständlich sein (ich denke assoziative Container)
Matthieu M.
3
@Fred: Immer wenn Ihre Grenzen nicht begin()und end()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.
Dennis Zickefoose
6
@geotavros: Und r_and_t<r_and_t<r_char_t<char>&, r_char_t<char>&>, r_char_t<char>&>tut?
Dennis Zickefoose
7
@geotavros: Oder Sie können sehen, was Typ spaceist, 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 bedeutet space & space & spacedas?". Der eigentliche Typ des Ausdrucks ist nur Rauschen.
Dennis Zickefoose
19

auto kann in Kombination mit Ausdrucksvorlagen, die häufig von linearen Algebra-Bibliotheken wie Eigen oder OpenCV verwendet werden, sehr gefährlich sein.

auto A = Matrix(...);
auto B = Matrix(...);
auto C = A * B; // C is not a matrix. It is a matrix EXPRESSION.
cout << C; // The expression is evaluated and gives the expected result.
... // <code modifying A or B>
cout << C; // The expression is evaluated AGAIN and gives a DIFFERENT result.

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.

auto C = Matrix(A * B); // The expression is now evaluated immediately.
morotspaj
quelle
1
Das scheint zunächst ein seltsames Verhalten zu sein. Wenn ich zwei Matrizen multipliziere, selbst wenn die Operation faul ist, würde ich nicht erwarten, dass sie erneut ausgewertet werden kann. Ich würde erwarten, dass sie nach der ersten Auswertung ihren ausgewerteten Zustand beibehält. Wenn Sie die Parameter ändern möchten, ohne die ursprünglichen Parameter zu ändern, müssten Sie den Ausdruck dann nicht trotzdem neu erstellen? Oder ist es für eine Streaming-Verarbeitungssituation konzipiert, in der sich die ursprünglichen Parameter ständig ändern, die Vorgehensweise jedoch gleich bleibt?
JAB
1
Unabhängig davon, ob der A*BAusdruck in eine autoVariable oder in etwas anderes kopiert wird oder nicht , ist das von Ihnen beschriebene Verhalten weiterhin vorhanden.
xtofl
Durch die Verwendung wird kein Fehler verursachtauto .
Jim Balter
@JAB: Es wurde entwickelt, um Vereinfachungen und Synergien zwischen Vorgängen zu unterstützen. Beispielsweise diag(A * B)müssen keine Zyklen für die Berechnung der nicht diagonalen Elemente verschwendet werden.
Ben Voigt
Ich habe auch Code wie 'for (auto o: vecContainer)' entdeckt, wobei 'o' ein schweres Objekt war, das jedes Mal kopiert wird. Meine Empfehlung wäre, es für das zu verwenden, was es ursprünglich beabsichtigt war, dh für Vorlagen (mit schwierigen Abzugsrichtlinien) und mühsame Typedefs. Selbst dann muss man vorsichtig sein und zwischen auto und auto & unterscheiden.
gast128
10

Ich benutze autoohne Einschränkung und hatte kein Problem. Ich benutze es sogar manchmal für einfache Typen wie int. 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 z

auto i = MyClass();

anstatt

MyClass i;

Dies ist ein Fall, in dem ich sagen würde, dass es sich um einen Missbrauch des autoSchlü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, autotut das nicht weh: z. B. auto s = mycollection.size()kann ich mir vorstellen, dass dies sder 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 in int_type s = mycollection.size()).

Zu diesem Beispiel aus der akzeptierten Antwort:

for ( auto x = max_size; x > 0; --x )

In meinem Code verwende ich autoin diesem Fall immer noch, und wenn ich nicht xsigniert werden möchte , verwende ich eine Dienstprogrammfunktion namens say make_unsigned, die meine Bedenken klar zum Ausdruck bringt:

for ( auto x = make_unsigned(max_size); x > 0; --x )

Haftungsausschluss: Ich beschreibe nur meine Verwendung, ich bin nicht kompetent, Ratschläge zu geben!

Rafak
quelle
1
@ChristianRau: war nicht sarkastisch. Beachten Sie, dass ich die Verwendung nicht empfohlen habe auto i = MyClass().
Rafak
3
Follow-up: siehe: herbsutter.com/2013/06/13/… . Die Verwendung von zB as_unsignedwird dort oder sogar empfohlen auto w = widget{};.
Rafak
3

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:

int main() {
    int x;
    int y = 0;
    y += x;
}

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.

main.cpp: In der Funktion 'int main ()':

main.cpp: 4: 8: Warnung : 'x' wird in dieser Funktion nicht initialisiert verwendet [-Wuninitialisiert]

y + = x;

    ^

================================================== ============================== Wenn wir nun unser Programm ändern, das auto verwendet , erhalten wir beim Kompilieren Folgendes:

int main() {
    auto x;
    auto y = 0;
    y += x;
}

main.cpp: In der Funktion 'int main ()':

main.cpp: 2: 10: Fehler : Die Deklaration von 'auto x' hat keinen Initialisierer

 auto x;

      ^

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

Mantosh Kumar
quelle
2
Ja. Und um den Typ anzugeben, können Sie ihn als 0i, 0u, 0l, 0ul, 0.0f, 0.0 oder sogar int (), unsigned (), double () usw. initialisieren
Robinson
6
Dieses Argument ist lächerlich. Sie sagen "Sie können den Initialisierer nicht vergessen, weil Sie einen Compilerfehler erhalten", aber dafür müssen Sie daran denken, ihn zu verwenden auto.
Leichtigkeitsrennen im Orbit
1
@LightnessRacesinOrbit: Ich habe dieses Konzept aus dem Herb Sutter-Vortrag realisiert (gelernt). Ich fand es logisch / praktisch Ratschläge von Kräutergesprächen, daher dachte ich, sie mit der Gemeinschaft zu teilen.
Mantosh Kumar
2
Ich denke nicht, dass dies eine gute Motivation ist, Auto zu verwenden. Aktivieren Sie einfach das Warnflag Ihres Compilers für die Verwendung nicht initialisierter Variablen und adressieren Sie alle Warnungen. Das heißt nicht, dass Sie es nicht verwenden sollten auto- aber Sie brauchen es nicht, um dieses Problem zu vermeiden.
Einpoklum
2

Eine Gefahr, die ich festgestellt habe, sind Referenzen. z.B

MyBigObject& ref_to_big_object= big_object;
auto another_ref = ref_to_big_object; // ?

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.

auto another_ref = function_returning_ref_to_big_object();

Sie würden "auto &" oder "const auto &" benötigen

MyBigObject& ref_to_big_object= big_object;
auto& another_ref = ref_to_big_object;
const auto& yet_another_ref = function_returning_ref_to_big_object();
user2495422
quelle
1

Verwenden autoSie 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.

LainIwakura
quelle
4
"wo es Sinn macht ..." ist der schwierige Teil. Programmierer können sich so sehr mit den Details der Codierung beschäftigen, dass sie nicht mehr wissen, was für andere Programmierer, insbesondere für zukünftige Betreuer, sinnvoll ist.
DarenW
Das stimmt, obwohl ich denke, dass es ziemlich einfach ist zu sagen, wann es mehrdeutig ist. Verwenden Sie im Zweifelsfall einen Kommentar!
LainIwakura
1
Wäre es nicht sinnvoll, einen Typ zu verwenden?
Mikhail
Einige Entwickler würden sagen, dass der Typ immer abgeleitet werden sollte!
Arafangion
Verwenden Sie einen Kommentar ...... oder verwenden Sie einfach den Typ und es wird kein Kommentar benötigt?
user997112
1

autoDas 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, sizeofmeldet ihn korrekt, decltypewürde den richtigen Typ angeben - es gibt keinen Schaden. Ich zähle nie autoals überstrapaziert!

Ajay
quelle
0

TL; DR: Siehe Faustregel unten.

Die akzeptierte Antwort schlägt die folgende Faustregel vor:

Verwenden autoSie diese Option immer dann, wenn es schwierig ist zu sagen, wie der Typ auf den ersten Blick geschrieben werden soll, der Typ der rechten Seite eines Ausdrucks jedoch offensichtlich ist.

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:

auto x = f();

Was macht dies zu einem Beispiel für Missbrauch auto? Ist es meine Unkenntnis des f()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 das xund f()sind ziemlich bedeutungslos. Wenn wir hätten:

auto nugget = mine_gold();

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, autowann immer der Compiler dies zulässt, es sei denn:

  • Sie haben das Gefühl, dass der Variablenname zusammen mit dem Initialisierungs- / Zuweisungsausdruck nicht genügend Informationen darüber liefert, was die Anweisung tut.
  • Sie glauben, dass der Variablenname zusammen mit dem Initialisierungs- / Zuweisungsausdruck "irreführende" Informationen darüber liefert, was der Typ sein sollte - dh wenn Sie raten müssten, was anstelle des Autos kommt, könnten Sie eine Vermutung anstellen - und das wäre es falsch, und diese falsche Annahme hat später im Code Auswirkungen.
  • Sie möchten einen anderen Typ erzwingen (z. B. eine Referenz).

Und auch:

  • Geben Sie lieber einen aussagekräftigen Namen (der natürlich nicht den Typnamen enthält), bevor Sie ihn durch autoden konkreten Typ ersetzen .
einpoklum
quelle
-3

Eine meiner bitteren Erfahrungen mit autoist die Verwendung mit Lambda-Ausdrücken :

auto i = []() { return 0; };
cout<<"i = "<<i<<endl; // output: 1 !!!

Eigentlich wird hier ider Funktionszeiger von aufgelöst int(*)(). Dies ist nur eine einfache cout, aber stellen Sie sich vor, welche Art von fehlerhaften Kompilierungs- / Laufzeitfehlern sie bei Verwendung verursachen können template.

Sie sollten solche Ausdrücke vermeiden auto und einen geeigneten returnTyp (oder einen kontrollierten decltype()) eingeben.

Die korrekte Verwendung für das obige Beispiel wäre:

auto i = []() { return 0; }(); // and now i contains the result of calling the lambda  
iammilind
quelle
7
Sie haben schrecklich erklärt, was das mit Auto zu tun hat. Sie haben eine Funktion erstellt und dann gedruckt ... Okay?
Dennis Zickefoose
5
@iammilind: und was hat das mit auto zu tun?
R. Martinho Fernandes
7
Ich finde es höchst unwahrscheinlich, dass man ()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.
R. Martinho Fernandes
4
Können Sie zumindest ein Szenario beschreiben , in dem es ohne Lambda auto x = []() { /* .... whatever goes in here ... */ }()besser ist als auto x = /* .... whatever goes in here ... */;dasselbe? Ich finde das ziemlich sinnlos, aus dem gleichen Grund auto x = 42 + y - 42ist es sinnlos.
R. Martinho Fernandes
6
-1 Dies ist nicht die Schuld von Auto. Der Typ eines Lambda kann nicht geschrieben werden, daher ist Auto erforderlich . Wenn Sie vergessen, die Funktion aufzurufen , ist dies Ihr eigener Ausguck! Sie können einen nicht aufgerufenen Funktionszeiger genauso willkürlich in einen C-Druck einfügen.
Spraff