编程语言
首页 > 编程语言> > 《Effective Modern C++》学习笔记 - Item 2: 理解auto类型推导

《Effective Modern C++》学习笔记 - Item 2: 理解auto类型推导

作者:互联网

auto x = 27; 			// 等价于以下模板推导
template<typename T> 	// 推导x类型的假想模板,下同
void func_for_x(T param); 
func_for_x(27); 

const auto cx = x;		// 等价于以下模板推导
template<typename T>
void func_for_cx(const T param);
func_for_cx(x);

const auto& rx = x;		// 等价于以下模板推导
template<typename T>
void func_for_rx(const T& param);
func_for_rx(x);
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[] = "hello";
auto  arr1 = name;	// arr1是const char*
auto& arr2 = name;	// arr2是const char (&)[13]

void someFunc(int, double);
auto  func1 = someFunc; // func1是void (*)(int, double)
auto& func2 = someFunc;	// func2是void (&)(int, double)
// 都将x初始化为int值27
int x1 = 27;
int x2(27);
int x3 = { 27 };
int x4{ 27 };

但如果直接将标识符改为 auto,这些声明仍都能通过编译,但意思不同。前两个仍声明一个值为27的 int但后两个声明的是包含一个元素27的 std::initializer_list<int>

auto x1 = 27;		// 类型为int,值为27
auto x2(27);		// 同上
auto x3 = { 27 };	// 类型为std::initializer_list<int>, 值为 { 27 }
auto x4{ 27 };		// 同上

这是由于 auto 类型推导的一条特殊规则:当使用大括号包围的初始化器(initializer)对一个 auto 描述的变量进行初始化时,推导出的类型是 std::initializer_list。如果推导不出这样的类型(如大括号包围的初始化器中有多个不同类型的元素)时,代码会编译报错。

要理解这里其实是一个两步的推导过程:由于 x 使用 大括号初始化,首先要推导出 xstd::initializer_list<T>,而后者又是一个模板,所以要从初始化列表中推出 T 的类型。

以上适用于 auto 的规则并不适用于模板推导,例如以下代码会报错:

template<typename T>
void f(T param);

f({ 11, 23, 9 }); // error!

解决方法为:

template<typename T>
void f(std::initializer_list<T> initList);
f({ 11, 23, 9 });
auto createInitList()
{
	return { 1, 2, 3 }; // error
}

std::vector<int> v;
auto resetV =
	[&v](const auto& newValue) { v = newValue; }; // C++14
resetV({ 1, 2, 3 }); 	// error

总结

  1. auto 类型推导通常与模板类型推导相同,但 auto 类型推导将大括号包裹的初始化器(initializer)识别为 std::initializer_list,而模板类型推导不会。
  2. auto 在函数返回值类型或lambda函数参数中遵循模板类型推导规则,而不是auto 类型推导的规则。

标签:27,Effective,推导,int,auto,Modern,类型,模板
来源: https://blog.csdn.net/Altair_alpha/article/details/121949230