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;
}
相关推荐
励志成为嵌入式工程师4 分钟前
c语言简单编程练习9
c语言·开发语言·算法·vim
捕鲸叉34 分钟前
创建线程时传递参数给线程
开发语言·c++·算法
A charmer39 分钟前
【C++】vector 类深度解析:探索动态数组的奥秘
开发语言·c++·算法
Peter_chq41 分钟前
【操作系统】基于环形队列的生产消费模型
linux·c语言·开发语言·c++·后端
记录成长java2 小时前
ServletContext,Cookie,HttpSession的使用
java·开发语言·servlet
前端青山2 小时前
Node.js-增强 API 安全性和性能优化
开发语言·前端·javascript·性能优化·前端框架·node.js
青花瓷2 小时前
C++__XCode工程中Debug版本库向Release版本库的切换
c++·xcode
睡觉谁叫~~~2 小时前
一文解秘Rust如何与Java互操作
java·开发语言·后端·rust
音徽编程2 小时前
Rust异步运行时框架tokio保姆级教程
开发语言·网络·rust
观音山保我别报错2 小时前
C语言扫雷小游戏
c语言·开发语言·算法