auto占位符(C++11~C++17)

文章目录

      • [1. 定义](#1. 定义)
        • [1.1 注意事项](#1.1 注意事项)
      • [2. 推导规则](#2. 推导规则)
      • [3. 返回类型推导(C++14)](#3. 返回类型推导(C++14))
      • [4. lambda表达式中使用auto类型推导](#4. lambda表达式中使用auto类型推导)
      • [5. 非类型模板形参占位符(C++17)](#5. 非类型模板形参占位符(C++17))

1. 定义

在C++11以前,auto关键字是用来声明自动变量的。从C++11起auto被用来:声明变量时根据初始化表达式自动推断该变量的类型、声明函数时函数返回值的占位符。

cpp 复制代码
auto a = 5;			// 推断为int
auto b = "Hello";	// 推断为const char*

// 返回类型后置, auto为返回值占位符(主要用于函数模板的返回值推导)
auto fun(int x, int y) -> int
{
	return x + y;
}

auto占位符会让编译器去推导变量的类型。若编写的代码让编译器无法推导则会编译失败,例如:

cpp 复制代码
auto a;	// 推导失败
a = 5;

编译器报错:

由此可知,在使用auto占位符声明变量时必须初始化变量。

1.1 注意事项
  1. 当用一个auto关键字声明多个变量时,编译器遵从由左往右的推导规则,以最左边的表达式推断auto类型。
cpp 复制代码
int a = 5;
auto* p = &a, m = 10;	// auto被推断为int, 所以m为int
  1. 当使用条件表达式初始化auto声明的变量时,编译器总是使用表达能力更强的类型。
cpp 复制代码
auto a = true ? 5 : 5.0;	// a被推断为double类型

通过反汇编查看可得

  1. 静态成员变量可以用auto声明并初始化,前提是auto必须用const限定符。
cpp 复制代码
class CusType
{
	auto a = 0;					// 错误,无法通过编译
	static const auto b = 0;	// 正确
	static inline auto c = 0;	// C++17支持 (测试环境VS2019编译失败,linux g++可以)
};
  1. 在C++20之前,无法在函数形参列表中使用auto声明形参(在C++14中,auto可以为lambda表达式声明形参)。
cpp 复制代码
int fun(auto a)		//  C++20之前编译失败,C++20编译成功 (测试VS2019编译失败)
{
	return a * 10;
}

auto 也可以和new关键字结合

cpp 复制代码
auto p = new auto(5);

2. 推导规则

  1. 如果auto声明的变量是按值初始化,则推导出的类型会忽略cv限定符(即const和volatile)。
cpp 复制代码
	const int a = 0;
	auto b = a;			// auto推导类型为int, b为int
	auto& c = a;		// auto推导类型为const int, c为const int&
	auto* d = &a;		// auto推到类型为const int, d为const int*
	const auto e = a;	// auto推导类型为int, e为const int
  1. 使用auto声明变量初始化时,目标对象如果是引用,则引用属性会被忽略。
cpp 复制代码
	int a = 0;
	int& b = a;
	auto c = b;		// auto推导为int
  1. 使用auto和万能引用(&&)声明变量时,对于左值会将auto推导为引用类型。
cpp 复制代码
	int a = 0;
	auto&& b = a;	// 推导为int&
	auto&& c = 1;	// 推导为int
  1. 使用auto声明变量,如果目标对象是一个数组或函数,则会被推导为对应的指针类型。
cpp 复制代码
int fun(int x)
{
	return x * x;
}

int main()
{
	
	int a[8] = {0};
	auto b = a;		// 推导为int*
	auto c = fun;	// 推导为int(*)(int)

	return 0;
}
  1. 当auto与列表初始化组合时(C++17),①直接使用列表初始化,列表必须为单元素,auto推导为元素类型;②用等号加列表初始化,列表中可以包含单个或多个元素,auto被推导为std::initializer_list<T>,T为元素类型。
cpp 复制代码
	auto a{ 1 };		// 推导为int
	auto b{ 1, 2, 3 };	// 编译失败,不是单个元素

cpp 复制代码
	auto a = { 1 };		// 推导为std::initializer_list<int>
	auto b = { 1, 2.0 };// 编译失败,列表内元素类型不同
	auto c = { 1, 8 };	// 推导为std::initializer_list<int>

3. 返回类型推导(C++14)

cpp 复制代码
auto sum(int x, int y)	// auto推导为int
{
	return x+y;
}

注意:如果有多个return,需保证返回值类型都相同才行。

4. lambda表达式中使用auto类型推导

cpp 复制代码
	auto a = [](auto x, auto y)	// C++14,lambda形参用auto;
	{
		return x + y;
	};
	auto ret = a(14, 23.3);		// 返回值推导为double

lambda返回auto引用:

cpp 复制代码
	auto fun = [](int& x) ->auto&
	{
		return x;
	};

	auto a = 1;
	auto& b = fun(a);
	assert(&a == &b);	// 有相同的内存地址

5. 非类型模板形参占位符(C++17)

cpp 复制代码
template<auto N>
void fun()
{
	cout << N << endl;
}

int main()
{
	fun<5>();	// N为int类型
	fun<'c'>(); // N为char类型
	fun<5.2>(); // 编译失败,模板参数不能为double

	return 0;
}
相关推荐
lozhyf12 分钟前
Go语言-学习一
开发语言·学习·golang
dujunqiu22 分钟前
bash: ./xxx: No such file or directory
开发语言·bash
爱偷懒的程序源25 分钟前
解决go.mod文件中replace不生效的问题
开发语言·golang
日月星宿~25 分钟前
【JVM】调优
java·开发语言·jvm
捕鲸叉34 分钟前
Linux/C/C++下怎样进行软件性能分析(CPU/GPU/Memory)
c++·软件调试·软件验证
2401_8437852334 分钟前
C语言 指针_野指针 指针运算
c语言·开发语言
Jacob程序员1 小时前
leaflet绘制室内平面图
android·开发语言·javascript
AitTech1 小时前
C#编程:List.ForEach与foreach循环的深度对比
开发语言·c#·list
阿俊仔(摸鱼版)1 小时前
Python 常用运维模块之OS模块篇
运维·开发语言·python·云服务器
军训猫猫头1 小时前
56.命令绑定 C#例子 WPF例子
开发语言·c#·wpf