Стандарт C ++ объясняет, что auto вычитается из значения инициализатора:
Объявления [dcl.spec.auto]/1:
Спецификаторы типа auto
и decltype(auto)
используются для обозначения типа заполнителя, который будетпозже заменяется вычетом из инициализатора.
Инициализаторы [dcl.init]/1:
Декларатор может указать начальное значение для объявленного идентификатора.
Таким образом, когда вы пишете следующие объявления:
int t = f(10);
auto x = y;
auto child = getChild();
правая сторона равна , вычисляемому как выражение , которое дает значение.И это значение используется для инициализации переменной, объявленной слева.
Значение не является ссылкой.Это не как указатели и адреса.В оценке выражения, всякий раз, когда используется ссылка, учитывается значение ссылки.Это можно увидеть с помощью следующего простого фрагмента:
int x=15;
int&y = x;
cout << x <<", " << y <<", " << &x<<endl;
cout << typeid(x).name() <<", " << typeid(y).name() <<", " << typeid(&x).name() <<endl;
В данном случае значение выражения, следовательно, равно Parent
, а не Parent &
.Вот почему ваш auto
будет выведен на тип Parent
.
Однако стандарт C ++ не рассматривает все значения одинаково.В [basic.lval]
это делает важное различие между различными типами значений, которые могут быть lvalues , xvalues и prvalues .В вашем случае getChild()
соответствует lvalue, который является объектом, на который вы ссылались, а не какой-то его временной копией.
Если у вас есть такое lvalue, вы можете создать ссылку на него:
[dcl.ref]
/ 2: ссылочный тип, объявленный с использованием &
, называется lvalueссылка, (...)
Но вам нужно сделать это явно, сказав, что ваше авто должно быть ссылкой:
auto &child = getChild();
Редактировать: Больше информации о том, как работает авто: Блог Херба Саттера GotW