auto类型推导

auto 类型推导就是模板类型推导,只有一个例外;关于模板类型推导参考这篇文章, 当一个变量被声明为auto ,auto相当于模板中的T ,而对变量做的相关的类型限定就像ParamType

  1. 类型声明是一个指针或者是一个引用,但不是一个通用的引用
  2. 类型声明是一个通用引用
  3. 类型声明既不是一个指针也不是一个引用

例如:

auto nTmp = 100; // 符合第3种情况

const auto nConstTmp = nTmp; // 没有符合的一种情况

const auto& nConstRefTmp = nTmp; // 非通用引用

auto&& uref1 = nTmp; // nTmp是int并且是左值所以uref1的类型是int&

auto&& uref2 = nConstTmp; // nConstTmp是int并且是左值所以uref2的类型是const int&

auto&& uref3 = 100; // 100是int并且是右值所以uref3的类型是int&&

在非引用类型声明里,数组和函数名称如何退化成指针。这在 auto 类型推导上面也是一样:

const char name[] = "zhangsan"; // name的类型是const char[8];

auto arr1 = name; // arr1的类型是const char*

auto& arr2 = name; // arr2的类型是const char (&)[8]

void ProcessFun(int nParam);

auto& func1 = ProcessFun; // func1的类型是void (&)(int)

例外


auto类型推导唯一一个与模板类型推导不同的地方就是在大括号{}的使用上,关于大括号的使用可以参考这篇文章

auto init1 = {100}; // 类型是std::intializer_list<int> 值是{ 100 }

auto init2{100}; // 同上

对待大括号初始化的行为是auto唯一和模板类型推导不一样的地方。当 auto 声明变量被使用一对大括号初始化,推导的类型是 std::intializer_list 的一个实例。但是如果相同的初始化递给相同的模板,类型推导会失败,代码不能编译

template<class T>
void TemplateFun(T param);

TemplateFun({1,2,3,4}); // 没办法推导T的类型

如果你明确模板的param的类型是一个不知道T类型的 std::initializer_list便可以使用大括号:

template<class T>
void TemplateFun(std::initializer_list<T> initList);
TemplateFun({ 11, 23, 9 }); // T被推导成int,initList的类型是std::initializer_list<int>

所以 auto 和模板类型推导的本质区别就是 auto 假设大括号初始化代表的是std::initializer_list,但是模板类型推导却不是

C++14允许auto表示推导的函数返回值,而且C++14的lambda可能会在参数声明里面使用auto。但是,这里面的使用是复用了模板的类型推导,而不是 auto 的类型推导。所以一个使用 auto 声明的返回值的函数或者auto用在参数类型声明,返回一个大括号初始化或者以大括号作为参数就无法编译

auto createInitList()
{
	return { 1, 2, 3 }; // 编译错误:不能推导出{ 1, 2, 3 }的类型
}

auto SetFun = [](const auto& newVal){...};
SetFun({1,2,3}); // 编译错误,不能推导出{ 1, 2, 3 }的类型

最后


  1. auto 类型推导通常和模板类型推导类似,但是auto类型推导假定大括号初始化代表的类型是std::initializer_list ,但是模板类型推导却不是这样

  2. auto 在函数返回值或者lambda参数里面执行模板的类型推导,而不是通常意义的auto类型推导