2015-11-13 17 views
45

Quando uso auto per dedurre un tipo di puntatore, ho trovato un fenomeno strano. Il mio codice è simile a questo:Uso di auto in C++ 11

#include <iostream> 
using namespace std; 
int main() 
{ 
    int i = 100; 
    auto p1 = &i; 
    auto *p2 = &i; 

    cout << *p1 << " " << *p2 << endl; 

    return 0; 
} 

Dopo la compilazione e l'esecuzione, possiamo trovare che il risultato di *p1 e *p2 è la stessa, sia 100. Questo significa p1 e p2 sono entrambi un oggetto puntatore che punta a un int oggetto.

[[email protected] ~]$ ./test 
100 100 

C'è qualche differenza tra queste due affermazioni che definiscono p1 e p2?

+9

Ovviamente, cos'altro potrebbe accadere? Se p1 e p2 non erano entrambi i puntatori, non è possibile inizializzarli con '& i'.Forse dovresti scrivere (e pensare) in termini di 'auto * p2' not' auto * p2' per chiarire che 'p2' è una variabile di un tipo di puntatore, con il tipo puntato automaticamente dedotto dal compilatore . –

+1

'auto * p2 = init()' impone il tipo di puntatore non elaborato. Potrebbe essere utile se ad es. un giorno 'init()' è refactored per restituire 'shared_ptr ' e invece di copiare questo valore e mantenere quel 'T' in memoria, si ottiene un errore di compilazione e si ha la possibilità di decidere se usare' shared_ptr ',' weak_ptr ', o' T & '. – jingyu9575

+1

Ecco perché 'auto' è sia magico che potenzialmente confuso. –

risposta

19

auto specificatore utilizzato in dichiarazioni di variabili, deduce il tipo con le stesse regole utilizzate in template argument deduction.

Considerare il primo esempio (ad esempio, auto p1 = &i;). Il tipo di auto specificatore si deduce come segue:

  1. auto viene sostituito con un parametro di template tipo immaginario (ad esempio, U p1 = &i;).
  2. &i tipo è int*, quindi senza sorprese e in base alle regole di deduzione modello U viene dedotto a int*.

Considerate ora il vostro secondo esempio (ad esempio, auto *p2 = &i).

  1. Ancora auto viene sostituito con un parametro di template tipo immaginario (ad esempio, U* p1 = &i;).
  2. &i tipo è int*, quindi in base alle regole di detrazione modello U viene dedotto a int.

Come tale, nel auto *p2 = &i; il tipo di segnaposto auto sarà correttamente dedurre come int e non come int*, che si tradurrebbe in p2 essere di tipo int**, come si sarebbe potuto aspettare.

+2

+1 per menzionare la regola di deduzione degli argomenti del modello. Tuttavia, come nota, la deduzione di tipo "auto" ha una piccola differenza rispetto alla deduzione del tipo di modello (vedi C++ moderno efficace di Meyers), anche se non ricordo i dettagli. –

+3

La differenza è dovuta agli elenchi di inizializzazione delle parentesi graffe: auto x = {1,2,3}. Citato dal libro di Scott Meyers (Effective modern C++): "la deduzione del tipo automatico è solitamente uguale alla deduzione del tipo di modello, ma la deduzione del tipo automatico presuppone che un inizializzatore rinforzato rappresenti uno std :: initializer_list e la deduzione del tipo di modello no". – spraetor

84

La differenza è che nel primo caso automatica viene dedotta per int* mentre nel secondo caso si deduce automatica a int, che si traduce in entrambi p1 e p2 essendo di tipo int*. Il meccanismo di deduzione del tipo per auto è equivalente a quello degli argomenti del modello. Il tipo di detrazione in esempio è quindi simile a

template<typename T> 
void foo(T p1); 

template<typename T> 
void bar(T* p2); 

int main() 
{ 
    int i; 
    foo(&i); 
    bar(&i); 
} 

dove entrambe le funzioni sono istanziati come tipo void (int *), ma nel primo caso T si deduce a int* mentre nel secondo caso è T digitare int.

+8

in aumento per la definizione dell'istanza di modello equivalente –