2015-11-13 5 views
45

Когда я использую auto для вывода типа указателя, я обнаружил странное явление. Мой код выглядит так:Использование auto в C++ 11

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

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

    return 0; 
} 

После компиляции и выполнения, мы можем обнаружить, что результат *p1 и *p2 такой же, как 100. Это означает, что p1 и p2 оба объекта указатель, который указывает на int объект.

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

Есть ли разница между этими двумя утверждениями, которые определяют p1 и p2?

+9

Конечно, что еще может произойти? Если p1 и p2 не оба указателя, вы не можете инициализировать их с помощью '& i'.Может быть, вы должны написать (и подумать) в терминах 'auto * p2'' '' '' '' '' '' '' '' '', чтобы было ясно, что '' p2' является переменной типа указателя, с указанным типом, автоматически выведенным компилятором , –

+1

'auto * p2 = init()' устанавливает тип необработанного указателя. Может быть полезно, если, например, someday 'init()' реорганизуется для возврата 'shared_ptr ' и вместо копирования этого значения и сохранения этого 'T' в памяти вы получаете ошибку компиляции и имеете возможность решить, использовать ли' shared_ptr ',' weak_ptr ', или' T & '. – jingyu9575

+1

Вот почему 'auto' является одновременно магическим и потенциально запутанным. –

ответ

19

auto спецификатор используется в объявлениях переменных, выводит его тип с теми же правилами, как он используется в template argument deduction.

Рассмотрите ваш первый пример (т. Е. auto p1 = &i;). Тип auto спецификатора выводится следующим образом:

  1. auto заменяется параметром шаблона мнимая типа (например, U p1 = &i;).
  2. &i тип int*, поэтому без сюрпризов и в соответствии с правилами вычета шаблонов U выведено на int*.

Теперь рассмотрим ваш второй пример (т. Е. auto *p2 = &i).

  1. Опять auto заменяется параметром шаблона мнимая типа (например, U* p1 = &i;).
  2. &i тип int*, поэтому в соответствии с правилами вычета шаблонов U выведено на int.

Таким образом, в auto *p2 = &i; тип заполнитель auto будет корректно выводится как int и не как int*, что приведет к p2 существа типа int**, как можно было бы ожидать.

+2

+1 для упоминания правила вывода аргумента шаблона. Однако, как примечание, дедукция типа 'auto' имеет одно небольшое отличие от вычитания типа шаблона (см.« Эффективный современный C++ »Meyers), хотя я не помню деталей. –

+3

Разница обусловлена ​​фигурными списками инициализаторов: auto x = {1,2,3}. Цитируется из книги Скотта Мейерса («Эффективный современный C++»): «Удержание автоматического типа обычно совпадает с вычитанием типа шаблона, но автоматический вывод типа предполагает, что бит инициализатор представляет собой std :: initializer_list, а вычет типа шаблона - нет». – spraetor

84

Разница заключается в том, что в первом случае автоматически выводится на int* в то время как во втором случае автоматически выводится на int, что приводит как p1 и p2 существа типа int*. Механизм дедукции типа для авто эквивалентен механизму аргументов шаблона. Тип вычет в вашем примере, поэтому похож на

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

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

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

, где обе функции реализованным, как тип пустот (INT *), но в первом случае T выводится на int* в то время как во втором случае T имеет тип int.

+8

, поддерживаемый для создания эквивалентного экземпляра шаблона –

Смежные вопросы