C++关键字auto

auto的使用

在命名变量时通常需要清楚地知道表达式的类型,然而目前C++的变量类型越来越复杂,准确记忆变量的类型变得困难,auto的引入可以使编译器替我们去分析表达式所属的类型,编译器通过初始值来推算变量的类型。针对《C++ Primer》第五版中的讲解添加自己的一些注解,理理思路。

内置基本数据类型与auto

如下所示,根据字面值0的类型推断为int,所以i的类型是int,p的类型是int*。

//通过0推算auto为int,相当于int i = 0, *p = &i;
auto i = 0, *p = &i;

auto可以在一条语句中声明多个变量,但一条声明语句只能有一个基本数据类型,所以该语句中所有变量的初始基本数据类型必须一样,如下为错误示范。

//错误!!sz的推算类型为int,pi的推算类型为	double
auto sz = 0, pi = 3.14;		
//错误!!如下所示,通过auto推算vector的大小类型时,想定义在此类型上的循环变量是错误的,编译器会根据a.size()和0分别推算,要确保类型一致
//在此例中,a.size()推算为long long unsigned int, 0推算为int,类型不一致。
std::vector<int> a{1, 2, 3, 4};
auto size = a.size(), b = 0;

复合类型(&、*)、常量与auto

使用引用真实目的是使用引用的对象,所以当引用被用作初始值时,编译器使用引用对象的类型作为auto的类型

//推算出a为int型
int i = 0, &r = i;
auto a = r;

用带有const属性的变量作为初始值时,auto会忽略掉顶层const,保留底层const

int i = 0, &r = i;
const int ci = i, &cr = ci;
auto b = ci;		//b的类型为int,因为ci中const属性是顶层const,被忽略掉

auto c = cr;		//c的类型为int,虽然cr是引用,const类型为底层const,但是如上所述,使用引用作为初始值时,编译器使用的是引用对象的类型
					//所以这里相当于用auto c = ci;推算为int
					
auto d = &i;		//d的类型为int*

auto e = &ci;		//e的类型为const int*,指向常量的指针
					//因为ci是顶层const,其取地址运算是一种底层const,所以auto保留下来底层const					

如果希望推算出auto类型是一个顶层const,需要明确指出

int i = 0;
const int ci = i;
const auto f = ci;	//f为const int型,ci推算为int,加上const即为f的类型

auto可以定义引用类型,设置一个类型为auto的引用时,初始值中的顶层const仍然保留

int i = 0;
const int ci = i;
auto &g = ci;		//g是整型常量引用,绑定到ci,即const int &g = ci;顶层const保留
auto &h = 42;		//错误!!不能为非常量引用绑定字面值,即int &h = 42;错误
const auto &j = 42;	//正确,为常量引用绑定字面值

&和*只从属于声明符,并不是基本数据类型的一部分,故初始值必须是同一类型

int i = 0;
const int ci = i;
auto &m = ci, *p = &ci;		//因为m是引用类型,ci中顶层const保留,推算为const int
							//对ci取地址是一种底层const,保留,推算为const int
							//两个初始值推算类型相同,正确,等价于const int &m = ci, *p = &ci;

内置数组与auto

数组有一个特性:在很多用到数组名字的地方,编译器会自动将其替换为指向数组首元素的指针。大多数表达式中,使用数组类型的对象其实是使用指向数组首元素的指针。因为,用数组作为auto变量的初始值时,推算出的类型是指针而不是数组。用数组初始化auto定义的引用时,推算类型仍然为数组。

int ia[] = {0, 1, 2, 3, 4, 5};
auto ia2 = ia, ia3(ia);		//ia2和ia3的类型为int*,实际相当于auto ia2 = &ia[0], ia3(&ia[0]);
ia2[0] = 100;
std::cout << ia3[0] << std::endl;	//输出100,利用指向数组的指针访问数组仍然可用
int arr[][4] = {1, 2, 3, 4, 5, 6, 7};
auto ia4(arr);	//ia4的类型为int (*)[4],是一个指针,指向包含4个整型的数组
				//用数组名做初始值替换为指向数组首元素的地址,在这里首元素为包含4个整型的数组,即auto ia4 = &arr[0];

auto ia5(arr[0]);	//ia5的类型为int*,是一个指向整型的指针
					//arr[0]是数组,则推算类型为指向数组首元素的指针

auto &ia6 = ia;		//ia6的类型为int [6]

范围for与auto

C++11新增范围for用于遍历序列

int ia[2][3] = {{1}, {2}};
//错误做法!!无法通过编译,row被推算为int*,不能用作下一层的范围for
for (auto row : ia)
	for (auto col : row)
		std::cout << col << std::endl;

//正确做法!!row被推算为int [3],仍然是序列
for (auto &row : ia)
	for (auto col : row)
		std::cout << col << std::endl;

其他

关于auto和其他关键字(比如new)以及和模板、函数的组合,参考文章C++ 11新特性的用法之auto

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值