Effective Modern C++:条款02

Aki 发布于 2022-12-02 327 次阅读


02理解auto型别推导:

首先我们需要明确的是auto型别推导与模板型别推导的运作原理几乎完全相同,如下所见:

auto x = 27;           // x型别为int
const auto cx = x;     // cx型别为const int
const auto& rx = x;    // rx型别为const int&
auto&& uref1 = x;      // x为int,且为左值,所以uref1类型为int&
auto&& uref2 = cx;     // cx为const int,为左值,所以uref2类型为const int&
auto&& uref3 = 27;     // 27为int,且为右值,所以uref3 类型为int&&
 
const char name[] = "this is test"; // name型别为const char[13]
auto arr1 = name;                   // arr1型别为const char*
auto& arr2 = name;                  // name型别为const char(&)[13]
 
void somefunc(int,double);  // somefunc是一个函数,型别为 void(int,double)
auto func1 = somefunc;      // func1类型为void(*)(int,double)
auto& func1 = somefunc;     // func2类型为void(&)(int,double)

C++11为了支持统一初始化,增加了大括号初始化表达式:

auto x1 = 27;    //x1型别为int
auto x2(27);     //x2型别为int 
auto x3 = {27};  //x3型别为std::initializer_list<int>,含有一个变量
auto x4{27};     //x4型别为int
auto x5 = {27,13,0.5};     //x5型别无法推导,编译报错,因为里面包含两种数据类型

在对大括号括起来的表达式进行推导时,auto会将其推导为一个std::initializer_list的类型,但是使用单个元素且不使用等号时却又能推导正确。

auto规定函数返回值:

在C++14中,auto可以作为函数返回值推导,但是注意,此时会视auto为模板型别推导;换句话说,想返回大括号序列不会识别为std::initializer_list,因此无法完成模板推导;

auto func()
{
  return {1,2,3};  // 编译报错,无法完成{1, 2, 3}的型别推导
}

lambda表达式捕获auto:

同理,使用auto来指定C++14中的lambda表达式形参型别时,也不能使用大括号括起来的初始化表达式来做实参:

std::vector<int> v;
auto resetV = [&v](const auto& new_value) {v = new_value};
 
resetV({1,2,3}); // 错误,无法完成{1,2,3}型别推导