在 采用auto
进行变量声明中,类型饰词取代了ParamType
,所以也存在三种情况
情况 1: 类型饰词是指针或引用,但不是万能引用
情况 2:类型饰词是万能引用
情况3: 类型饰词既非指针也非引用
auto x = 27; // 情况3
const auto cx = x; // 情况3
const auto& rx = x;// 情况1
auto&& uref1 = x; // x的类型为int,且为左值,所以uref1的类型为int&
auto&& uref2 = cx; // cx的类型为const int,且为左值,所以uref2的类型为const int&
auto&& uref3 = 27; // rx的类型为int,且为右值,所以uref3的类型为int &&
使用auto
声明变量时有如下规则:
auto x1 = 27; // 类型为int, 值为27
auto x2(27); // 同上
auto x3 = {27}; // 类型为std::initializere_list<int>,值为27
auto x4{27}; // 同上
这是一条有关auto
特殊的类型推导规则所致:当用于auto
声明变量的初始化表达式是使用大括号括起来时,推导所得的类型就属于std::initializer_list
;,如果大括号里面的值型不一样就会导致代码通不过编译。
auto x = {11, 23, 9}; // x的类型为std::initializer_list<int>
template<typename T> // 带有形参的模版
void f(T param); // 与x的声明等价的声明式
f({11, 23, 9}); // 错误,无法推导T的类型
auto
和模板类型推导真正的唯一区别在于,auto
会假定用大括号括起来的初始化表达式代表一个std::initializer_list
,但是模板类型推导却不会。
不过,你若指定改模板中param
的为std::initializer_list<T>
,则在T
的类型未知时,模板类型推导机制会推导出T
应有的类型:
template<typename T>
void f(std::initializer_list<T> initList);
f({11, 23, 9}); // T的类型推导为int,从而initList的类型为std::initiazlizer_list<int>
在函数返回值或者lambda
式子的形参中使用auto
,意思是使用模板类型推导而非auto
类型推导