C'è un aspetto negativo nella dichiarazione di variabili con auto in C ++?


143

Sembra che sia autostata aggiunta una caratteristica abbastanza significativa in C ++ 11 che sembra seguire molti dei linguaggi più recenti. Come in un linguaggio come Python, non ho visto alcuna dichiarazione esplicita di variabili (non sono sicuro che sia possibile utilizzare gli standard Python).

C'è un inconveniente nell'usare autoper dichiarare le variabili invece di dichiararle esplicitamente?



3
L'unico aspetto negativo che ho riscontrato è stato quando ho dovuto trasferire una base di codice su una piattaforma (console) il cui compilatore non supportava (e non aveva intenzione di supportare) le funzionalità C ++ 11!
Sam,

7
Solo per completezza GotW # 94 "Quasi sempre auto": herbsutter.com/2013/08/12/…
Richard Critten,

1
Stavo ascoltando cppcast e si parlava di clash b / n auto e inizializzatori di liste. Proverò a trovare quel podcast.
Abhinav Gauniyal,

2
il primo
aspetto

Risposte:


111

Mi hai solo chiesto degli svantaggi, quindi ne sto evidenziando alcuni. Se usato bene, autoha anche diversi vantaggi. Gli svantaggi derivano dalla facilità di abuso e dall'aumento del potenziale per il codice di comportarsi in modo non intenzionale.

Lo svantaggio principale è che, utilizzando auto, non si conosce necessariamente il tipo di oggetto che viene creato. Ci sono anche occasioni in cui il programmatore potrebbe aspettarsi che il compilatore deduca un tipo, ma il compilatore ne deduce categoricamente un altro.

Data una dichiarazione simile

auto result = CallSomeFunction(x,y,z);

non hai necessariamente conoscenza di che tipo resultsia. Potrebbe essere un int. Potrebbe essere un puntatore. Potrebbe essere qualcos'altro. Tutti supportano diverse operazioni. Puoi anche cambiare radicalmente il codice con una piccola modifica come

auto result = CallSomeFunction(a,y,z);

perché, a seconda di quali sovraccarichi esistono per CallSomeFunction()il tipo di risultato, potrebbe essere completamente diverso - e quindi il codice successivo potrebbe comportarsi in modo completamente diverso da quello previsto. Potresti innescare improvvisamente messaggi di errore nel codice successivo (ad es. Successivamente tentando di dereferenziare un int, cercando di cambiare qualcosa che è ora const). Il cambiamento più sinistro è il punto in cui la modifica passa oltre il compilatore, ma il codice successivo si comporta in modi diversi e sconosciuti, possibilmente con errori.

Non avere una conoscenza esplicita del tipo di alcune variabili rende quindi più difficile giustificare rigorosamente l'affermazione che il codice funziona come previsto. Ciò significa maggiori sforzi per giustificare le affermazioni di "idoneità allo scopo" in settori ad alta criticità (ad esempio critici per la sicurezza o mission-critical).

L'altro, svantaggio più comune, è la tentazione per un programmatore di utilizzare autocome strumento contundente per forzare la compilazione del codice, piuttosto che pensare a cosa sta facendo il codice e lavorare per farlo correttamente.


58
È interessante notare che se tali esempi sono lo svantaggio dell'uso auto, allora la maggior parte del linguaggio tipizzato da anatra presenta tale inconveniente dal design!
Leben Asa,

11
Se CallSomeFunction()restituisce un tipo diverso a seconda della sequenza dei suoi argomenti, questo è un difetto di progettazione di CallSomeFunction(), non un problema di auto. Se non leggi la documentazione di una funzione che stai utilizzando prima di usarla, questo è un difetto del programmatore, non un problema auto. - Ma capisco che qui interpreti l'avvocato del diavolo, è solo che Nir Friedman ha il caso molto migliore.
DevSolar

16
@DevSolar: perché sarebbe T CallSomeFunction(T, int, int)un difetto di progettazione? Ovviamente "restituisce un tipo diverso a seconda della sequenza dei suoi argomenti".
Salterio il

9
"Lo svantaggio principale è che, utilizzando auto, non si conosce necessariamente il tipo di oggetto che viene creato." Puoi approfondire il motivo per cui questo è un problema autoe non un problema con i provvisori della sottoespressione? Perché è auto result = foo();cattivo, ma foo().bar()no?
Angew non è più orgoglioso di SO

24
Dai commenti sembra che "l'inconveniente" sia interpretato come una ragione per cui qualcosa è inaccettabile. Uno svantaggio di una funzionalità linguistica è uno svantaggio che lo sviluppatore deve considerare e giustificare l'accettazione o meno, vale a dire effettuare compromessi di ingegneria. Non sto facendo affermazioni generali sul perché la funzione debba o non debba essere utilizzata.
Peter,

76

Questo non è autoesattamente uno svantaggio di principio, ma in termini pratici sembra essere un problema per alcuni. Fondamentalmente, alcune persone: a) trattano autocome un salvatore per i tipi e chiudono il cervello quando lo usano, oppure b) dimenticano che autosi deduce sempre ai tipi di valore. Questo fa sì che le persone facciano cose del genere:

auto x = my_obj.method_that_returns_reference();

Spiacenti, abbiamo appena copiato in profondità un oggetto. Spesso è un errore o un fallimento delle prestazioni. Quindi, puoi anche oscillare dall'altra parte:

const auto& stuff = *func_that_returns_unique_ptr();

Ora ottieni un riferimento penzolante. Questi problemi non sono affatto causati da auto, quindi non li considero argomenti legittimi contro di esso. Ma sembra autorendere questi problemi più comuni (per esperienza personale), per i motivi che ho elencato all'inizio.

Penso che, dato il tempo, le persone si adegueranno e comprenderanno la divisione del lavoro: ne autodeduce il tipo sottostante, ma tu vuoi ancora pensare a riferimento e costanza. Ma ci vuole un po 'di tempo.


Perché all'inizio puoi copiare in profondità un oggetto costoso?
Laurent LA RIZZA,

3
@LaurentLARIZZA: alcune classi hanno costruttori di copie semplicemente perché a volte sono necessarie (ad esempio, istanze di std::vector). Essere costosi da copiare non è una proprietà di una classe, ma di singoli oggetti. Quindi method_that_returns_referencepotrebbe riferirsi a un oggetto di una classe che ha un costruttore di copie, ma quale oggetto risulta essere piuttosto costoso da copiare (e da cui non può essere spostato).
Marc van Leeuwen,

@MarcvanLeeuwen: se l'oggetto è costoso da copiare e non può essere spostato, perché dovrebbe essere archiviato in un std::vector? (Perché potrebbe, sì, o perché non controlli la classe, ma non è questo il punto) Se è costoso da copiare, (e non possiede alcuna risorsa, perché è copiabile), perché non usare COW sull'oggetto? La località dei dati è già stata eliminata dalla dimensione dell'oggetto.
Laurent LA RIZZA,

2
@LaurentLARIZZA Non un'istanza di qualcosa di archiviato in un vettore che è costosa, solo un normale vettore <doppia> è costoso da copiare, è un'allocazione di heap + O (N). Lo spostamento è un'aringa rossa. La prima riga che ho mostrato verrà copiata, non spostata, a meno che il riferimento restituito sia un riferimento di valore. COW non è davvero né qui né lì. Il fatto è che esisterà sempre costoso copiare oggetti.
Nir Friedman,

4
@Yakk Non può farlo in modo sicuro, perché potrebbe tagliare. L'unica cosa sicura che può fare è = deletequel sovraccarico. Anche se più in generale ciò che dici è una soluzione. Questo è un argomento che ho approfondito, se sei interessato: nirfriedman.com/2016/01/18/… .
Nir Friedman,

51

Altre risposte citano inconvenienti come "non sai davvero quale sia il tipo di una variabile". Direi che questo è in gran parte correlato alla convenzione di denominazione sciatta nel codice. Se le tue interfacce hanno un nome chiaro, non dovresti preoccuparti di quale sia il tipo esatto. Certo, auto result = callSomeFunction(a, b);non ti dice molto. Ma auto valid = isValid(xmlFile, schema);ti dice abbastanza da usare validsenza preoccuparti del tipo esatto. Dopotutto, con just if (callSomeFunction(a, b)), non sapresti nemmeno il tipo. Lo stesso con qualsiasi altro oggetto temporaneo di sottoespressione. Quindi non lo considero un vero inconveniente di auto.

Direi che il suo principale svantaggio è che a volte il tipo esatto di restituzione non è quello con cui vuoi lavorare. In effetti, a volte il tipo restituito effettivo differisce dal tipo restituito "logico" come dettaglio di implementazione / ottimizzazione. I modelli di espressione sono un ottimo esempio. Diciamo che abbiamo questo:

SomeType operator* (const Matrix &lhs, const Vector &rhs);

Logicamente, ci aspetteremmo SomeTypedi esserlo Vectore vorremmo sicuramente trattarlo come tale nel nostro codice. Tuttavia, è possibile che ai fini dell'ottimizzazione, la libreria di algebra che stiamo utilizzando implementa i modelli di espressione e il tipo di ritorno effettivo è questo:

MultExpression<Matrix, Vector> operator* (const Matrix &lhs, const Vector &rhs);

Ora, il problema è che MultExpression<Matrix, Vector>con ogni probabilità verrà archiviato un const Matrix&e const Vector&internamente; si aspetta che si convertirà in a Vectorprima della fine della sua espressione completa. Se abbiamo questo codice, va tutto bene:

extern Matrix a, b, c;
extern Vector v;

void compute()
{
  Vector res = a * (b * (c * v));
  // do something with res
}

Tuttavia, se avessimo usato autoqui, potremmo avere dei problemi:

void compute()
{
  auto res = a * (b * (c * v));
  // Oops! Now `res` is referring to temporaries (such as (c * v)) which no longer exist
}

3
@NirFriedman Hai ragione, è forte, ma in realtà sento che autoha pochissimi inconvenienti, quindi sostengo quella forza. E altri esempi di proxy ecc. Includono vari "costruttori di stringhe" e oggetti simili trovati nei DSL.
Angew non è più orgoglioso di SO

2
Sono stato morso da modelli di espressione e autoprima, in particolare con la libreria Eigen. È particolarmente complicato perché il problema spesso non si presenta nelle build di debug.
Dan,

1
L'uso di autopuò anche mordere quando si utilizza la libreria di matrici Armadillo , che fa un uso intensivo della meta-programmazione di template per scopi di ottimizzazione. Fortunatamente gli sviluppatori hanno aggiunto la funzione .eval () che può essere usata per evitare i problemi conauto
mtall

2
"Se le tue interfacce hanno un nome chiaro, non dovresti preoccuparti di quale sia il tipo esatto" Il tuo compilatore non può verificare la correttezza del tuo codice studiando i nomi delle variabili. Questo è l'intero punto di un sistema di tipi. Aggirare ciecamente è sciocco!
Razze di leggerezza in orbita,

1
@Angew: Non è un problema per i provvisori perché di solito li usi immediatamente, il che senza autogeneralmente comporta un qualche tipo di controllo del tipo (e schizzi autoin tutto il mondo toglie quel tipo di sicurezza proprio come fa ovunque). Non è un buon confronto.
Corse di leggerezza in orbita,

13

Uno degli svantaggi è che a volte non è possibile dichiarare const_iteratorcon auto. Otterrai un iteratore ordinario (non const) in questo esempio di codice preso da questa domanda :

map<string,int> usa;
//...init usa
auto city_it = usa.find("New York");

3
Bene, ottieni iteratorcomunque in quanto la tua mappa non è const. se vuoi convertirlo in a const_iterator, specifica il tipo di variabile esplicitamente come al solito, oppure estrai un metodo in modo che la tua mappa sia costante nel contesto del tuo find. (Preferirei quest'ultimo. SRP.)
Laurent LA RIZZA,

auto city_it = static_cast<const auto&>(map).find("New York")? o, con C ++ 17, auto city_if = std::as_const(map).find("New York").
Dev Null,

11

Rende il tuo codice un po 'più difficile o noioso da leggere. Immagina qualcosa del genere:

auto output = doSomethingWithData(variables);

Ora, per capire il tipo di output, dovresti rintracciare la firma della doSomethingWithDatafunzione.


40
Non sempre. auto it = vec.begin();è molto più facile da leggere rispetto std::vector<std::wstring>::iterator it = vec.begin();ad esempio.
Jonathan Potter,

4
Concordato. Dipende dal caso d'uso. Avrei potuto essere più preciso al riguardo.
Skam

1
@SeeDart sì, le persone che usano l'auto in quel modo lo stanno facendo male.
lciamp,

6
"Rintraccia la firma della funzione", se non è un mouse o un tasto premuto ("segui il simbolo" / "vai alla dichiarazione" / come si chiama), devi configurare di più il tuo editor o passa a un IDE che può farlo senza configurazione ... Il tuo punto è comunque valido.
hyde,

6
Ho notato che non in un IDE ma in piccoli spioncini di diffs durante la revisione dei check-in! Con l'auto sono più difficili da leggere per questo motivo.
JDługosz,

10

Come questo sviluppatore, odio auto. O meglio, odio il modo in cui le persone abusano auto.

Sono del (forte) parere che autoè per aiutare a scrivere codice generico, non per ridurre la digitazione .
Il C ++ è un linguaggio il cui obiettivo è farti scrivere codice robusto, non minimizzare i tempi di sviluppo.
Ciò è abbastanza ovvio da molte funzionalità di C ++, ma sfortunatamente alcune di quelle più recenti come autoquella riducono la digitazione inducono le persone a pensare che dovrebbero iniziare a essere pigri con la digitazione.

In pre- autogiorni, la gente typedefs, che era fantastico, perché typedef ha permesso il progettista della biblioteca per aiutarti a capire quale sia il tipo di ritorno dovrebbe essere, in modo che le loro opere della biblioteca come previsto. Quando lo usi auto, togli il controllo al progettista della classe e chiedi invece al compilatore di capire quale dovrebbe essere il tipo, il che rimuove uno dei più potenti strumenti C ++ dalla casella degli strumenti e rischia di rompere il loro codice.

Generalmente, se lo usi auto, dovrebbe essere perché il tuo codice funziona per qualsiasi tipo ragionevole , non perché sei troppo pigro per scrivere il tipo con cui dovrebbe funzionare. Se utilizzi autocome strumento per aiutare la pigrizia, ciò che accade è che alla fine inizi a introdurre bug sottili nel tuo programma, di solito causati da conversioni implicite che non sono avvenute perché hai usato auto.

Sfortunatamente, questi bug sono difficili da illustrare in un breve esempio qui perché la loro brevità li rende meno convincenti rispetto agli esempi reali che emergono in un progetto utente - tuttavia, si verificano facilmente in un codice pesante di template che si aspetta che alcune conversioni implicite prendano posto.

Se vuoi un esempio, ce n'è uno qui . Un piccolo appunto, però: prima di essere tentati di saltare e criticare il codice: tieni presente che molte librerie ben note e mature sono state sviluppate attorno a conversioni così implicite e sono lì perché risolvono problemi che possono essere difficili se non impossibili per risolvere diversamente. Prova a trovare una soluzione migliore prima di criticarli.


3
which was great because typedef allowed the designer of the library to help you figure out what the return type should be, so that their library works as expected. When you use auto, you take away that control from the class's designer and instead ask the compiler to figure out what the type should beNon proprio una buona ragione per IMO. Gli IDE aggiornati, ad esempio Visual Studio 2015, consentono di verificare il tipo di variabile passando il mouse sopra auto. Questo è * esattamente * lo stesso di typedefquello.
Sombrero Chicken

@JameyD: In questo punto mancano alcuni punti cruciali: (1) L'argomento IDE funziona solo se il tipo è concreto, non basato su modelli. Gli IDE non possono dirti il ​​tipo corretto nel caso di tipi dipendenti, ad es typename std::iterator_traits<It>::value_type. (2) L' intero punto era che il tipo inferito non doveva necessariamente essere "esattamente lo stesso" del tipo corretto inteso dal precedente progettista del codice; utilizzando auto, stai togliendo la capacità del progettista di specificare il tipo corretto.
user541686

In pratica stai parlando di proxy, di cui una delle risposte menziona già. I modelli di espressioni e le sciocchezze <bool> vettoriali non sono un codice quotidiano per la maggior parte delle persone. Nella maggior parte dei casi, non si desidera conversioni implicite e l'auto aiuta in questo. Herb Sutter parla ampiamente dei vantaggi dell'auto in uno dei suoi post sul blog, e non si tratta principalmente di sequenze di tasti, e non è solo per il codice generico. Inoltre, il primo link che hai fornito, il post sul blog è semplicemente un consiglio terribile (motivo per cui è stato criticato rumorosamente nella sua sezione commenti).
Nir Friedman,

@NirFriedman: "... vector<bool>sciocchezze" ... scusa? Come pensi che bitsetsia implementato? O ritieni che i contenitori di bit siano del tutto privi di senso ?!
user541686,

1
@NirFriedman: nulla del vettore <bool> è una novità per me. Quello che sto cercando di dirti e che stai palesemente rifiutando di capire è che ai fini di questa domanda il set di bit non è diverso dal vettore <bool> - entrambi usano i proxy, perché i proxy erano ritenuti utili e il fatto che i proxy siano utili è una realtà che devi accettare invece di vivere nella negazione di. Puoi per favore smettere di trasformarlo in un dibattito sul fatto che pensi che i proxy siano utili? Questo non è argomento di dibattito, e anche la tua opinione su di essi è solo la tua opinione, non una sorta di fatto.
user541686,

6

autonon ha di per sé degli inconvenienti e io sostengo (agitando a mano) di usarlo ovunque nel nuovo codice. Consente al codice di controllare costantemente il tipo e di evitare costantemente lo slicing silenzioso. (Se Bderiva Ae una funzione che ritorna Aimprovvisamente ritorna B, si autocomporta come previsto per memorizzare il suo valore di ritorno)

Tuttavia, il codice precedente pre-C ++ 11 può fare affidamento su conversioni implicite indotte dall'uso di variabili tipizzate in modo esplicito. La modifica di una variabile esplicitamente digitata in autopotrebbe cambiare il comportamento del codice , quindi è meglio essere cauti.


Il downvoting è corretto, ma potresti commentare il perché?
Laurent LA RIZZA,

Non ti ho sottovalutato, ma autoha degli svantaggi di per sé (o almeno - molti pensano che lo faccia). Considera l'esempio fornito nella seconda domanda di questo panel di discussione con Sutter, Alexandrescu e Meyers: Se hai auto x = foo(); if (x) { bar(); } else { baz(); }e foo()ritorna bool- cosa succede se le foo()modifiche restituiscono un enum (tre opzioni anziché due)? Il autocodice continuerà a funzionare, ma produrrà risultati imprevisti.
einpoklum,

@einpoklum: E usare boolinvece di autocambiare qualcosa nel caso di un enum senza ambito? Potrei sbagliarmi (non posso controllare qui), ma penso che l'unica differenza sia che la conversione boolavvenga alla dichiarazione variabile invece che alla valutazione della condizione nel if. Se enumè nell'ambito, la conversione in boolnon deve avvenire senza un preavviso esplicito.
Laurent LA RIZZA,

4

La parola chiave autosemplicemente deduce il tipo dal valore restituito. Pertanto, non è equivalente a un oggetto Python, ad es

# Python
a
a = 10       # OK
a = "10"     # OK
a = ClassA() # OK

// C++
auto a;      // Unable to deduce variable a
auto a = 10; // OK
a = "10";    // Value of const char* can't be assigned to int
a = ClassA{} // Value of ClassA can't be assigned to int
a = 10.0;    // OK, implicit casting warning

Poiché autoviene dedotto durante la compilazione, non avrà alcun inconveniente durante l'esecuzione.


1
sì, fondamentalmente fa quello che fa type()in Python. Deduce il tipo, non crea una nuova variabile di quel tipo.
lciamp,

2
@lciamp In realtà, sarebbe decltype. autoè per assegnazione di variabili in particolare.
Cubico

4

Ciò che nessuno ha menzionato qui finora, ma per sé merita una risposta se me lo chiedessi.

Poiché (anche se tutti dovrebbero essere consapevoli del fatto C != C++) il codice scritto in C può essere facilmente progettato per fornire una base per il codice C ++ e quindi essere progettato senza troppi sforzi per essere compatibile con C ++, questo potrebbe essere un requisito per la progettazione.

Conosco alcune regole da cui alcuni costrutti ben definiti Cnon sono validi per C++e viceversa. Ma ciò si tradurrebbe semplicemente in eseguibili rotti e si applica la clausola UB nota che la maggior parte delle volte viene notata da strani loop che causano arresti anomali o altro (o possono anche non essere rilevati, ma non importa qui).

Ma autoè la prima volta 1 questo cambia!

Immagina di aver usato prima autocome identificatore della classe di archiviazione e di trasferire il codice. Non si spezzerebbe nemmeno necessariamente (a seconda del modo in cui è stato usato); in realtà potrebbe cambiare silenziosamente il comportamento del programma.

È qualcosa che dovresti tenere a mente.


1 Almeno la prima volta che ne sono a conoscenza.


1
Si otterrebbe comunque un errore del compilatore quando si tenta di compilare.
Sombrero Chicken

@JameyD: Cosa farebbe? perché 2 situazioni di codice valide con significato diverso dovrebbero mai essere restituite per errore?
Dhein,

8
Se fai affidamento su "nessun tipo implica int" in C, ti meriti tutte le cose cattive che otterrai da questo. E se non fai affidamento su di esso, l'utilizzo autocome identificatore della classe di archiviazione insieme a un tipo ti darà un buon errore di compilazione in C ++ (che è una buona cosa in questo caso).
Angew non è più orgoglioso di SO

1
@Angew bene, questo è il caso a cui mi riferisco, sì. Non lo sto facendo. Ma è qualcosa che dovrebbe almeno essere tenuto presente.
Dhein

3

Una ragione a cui riesco a pensare è che perdi l'opportunità di forzare la classe che viene restituita. Se la tua funzione o metodo ha restituito un lungo 64 bit e volevi solo 32 int senza segno, perdi l'opportunità di controllarlo.


1
C'è static_cast e IIRC, ad esempio, Effective Modern C ++ di Meyers consiglia persino di usarlo per specificare il tipo per la variabile digitata automaticamente.
hyde,

2

Come ho descritto in questa risposta, a auto volte può risultare in situazioni funky che non intendevi. Devi dire esplicitamente auto&di avere un tipo di riferimento mentre semplicemente autopuoi creare un tipo di puntatore. Ciò può causare confusione omettendo lo specificatore tutti insieme, risultando in una copia del riferimento anziché in un riferimento effettivo.


2
Non è strano. Questo è ciò che autofa, non inferendo mai un riferimento né un consttipo. Per un autoriferimento, è meglio usare auto&&. (un riferimento universale) Se il tipo non è economico da copiare o possiede una risorsa, allora il tipo non dovrebbe essere copiabile per cominciare.
Laurent LA RIZZA,

1

Un altro esempio irritante:

for (auto i = 0; i < s.size(); ++i)

genera un avviso ( comparison between signed and unsigned integer expressions [-Wsign-compare]), poiché iè un int firmato. Per evitare ciò è necessario scrivere ad es

for (auto i = 0U; i < s.size(); ++i)

o forse meglio:

for (auto i = 0ULL; i < s.size(); ++i)

1
Sì, trovo anche questo irritante. Ma il buco nella lingua è altrove. Affinché questo codice sia veramente portatile, supponendo i sizeritorni size_t, dovresti essere in grado di avere un valore size_tletterale 0z. Ma puoi dichiarare un UDL per farlo. ( size_t operator""_z(...))
Laurent LA RIZZA,

1
Obiezioni puramente teoriche: unsignedè molto probabile che non siano abbastanza grandi da contenere tutti i valori delle std::size_tarchitetture tradizionali, quindi nell'improbabile caso in cui qualcuno avesse un contenitore con un numero assurdamente gigantesco di elementi, l'utilizzo unsignedpotrebbe causare un ciclo infinito nell'intervallo inferiore di indici. Sebbene sia improbabile che ciò costituisca un problema, std::size_tdovrebbe essere utilizzato per ottenere un codice pulito che segnali correttamente l'intento. Non sono nemmeno sicuro che unsigned long longsia sufficiente, sebbene in pratica presumibilmente debba essere lo stesso.
underscore_d

@underscore_d: sì, punto giusto - unsigned long longè garantito essere almeno 64 bit, ma in teoria size_tpotrebbe essere più grande di questo, suppongo. Ovviamente se hai> 2 ^ 64 elementi nel tuo contenitore, potresti avere grossi problemi di cui preoccuparti ... ;-)
Paul R

1

Penso che autosia buono se usato in un contesto localizzato, in cui il lettore può facilmente e ovviamente dedurre il suo tipo, o ben documentato con un commento del suo tipo o un nome che inferisce il tipo reale. Chi non capisce come funziona potrebbe prenderlo nel modo sbagliato, come usarlo al posto di templateo simile. Ecco alcuni casi positivi e negativi secondo me.

void test (const int & a)
{
    // b is not const
    // b is not a reference

    auto b = a;

    // b type is decided by the compiler based on value of a
    // a is int
}

Buoni usi

iteratori

std::vector<boost::tuple<ClassWithLongName1,std::vector<ClassWithLongName2>,int> v();

..

std::vector<boost::tuple<ClassWithLongName1,std::vector<ClassWithLongName2>,int>::iterator it = v.begin();

// VS

auto vi = v.begin();

Puntatori di funzioni

int test (ClassWithLongName1 a, ClassWithLongName2 b, int c)
{
    ..
}

..

int (*fp)(ClassWithLongName1, ClassWithLongName2, int) = test;

// VS

auto *f = test;

Usi sbagliati

Flusso di dati

auto input = "";

..

auto output = test(input);

Firma della funzione

auto test (auto a, auto b, auto c)
{
    ..
}

Casi di prova

for(auto i = 0; i < 100; i++)
{
    ..
}

Quando vuoi un int, devi digitare un altro carattere se cerchi auto. È inaccettabile
Rerito,

@Rerito sì, è intfacilmente visibile qui e la digitazione intè più breve. Ecco perché è un caso banale.
Khaled.K,

0

Sono sorpreso che nessuno l'abbia menzionato, ma supponiamo che tu stia calcolando il fattoriale di qualcosa:

#include <iostream>
using namespace std;

int main() {
    auto n = 40;
    auto factorial = 1;

    for(int i = 1; i <=n; ++i)
    {
        factorial *= i;
    }

    cout << "Factorial of " << n << " = " << factorial <<endl;   
    cout << "Size of factorial: " << sizeof(factorial) << endl; 
    return 0;
}

Questo codice genererà questo:

Factorial of 40 = 0
Size of factorial: 4

Quello non era sicuramente il risultato atteso. Ciò è accaduto perché autodedotto il tipo di variabile fattoriale come intperché assegnato 1.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.