C++ auto关键字

Share on:
300 Words | Read in about 2 Min | View times

Overview

auto关键字在C++11中进行了重新定义,抛弃了传统C++中auto是用来自动延长对象生命周期的用法,而是将其用作类型自动推导。本节内容主要讨论auto的用法以及一些注意事项。

本系列文章将包括以下领域:

本章其他内容请见 《现代C++》

auto关键字的用法

auto关键字来声明变量类型的时候,会根据变量的初始化数值类型自动推导出变量的匹配类型,与decltype关键字的作用类似。

auto的类型推导发生在编译期,而不是运行期,所以使用auto关键字声明变量类型并不会降低效率。

代替冗长的类型声明

特别是对于容器迭代器的类型声明非常有用:

 1std::map<int, int> mp;
 2//传统写法,非常冗长
 3std::map<int, int>::iterator itr = mp.find(1);
 4if (itr != mp.end()) {
 5    //...
 6}
 7
 8//C++11写法
 9auto itr2 = mp.find(2);
10if (itr2 != mp.end()) {
11    //...
12}

用于声明模板函数中依赖模板参数的变量类型

1template<typename T1, typename T2>
2void Plus(T1 x, T2 y) {
3    auto result = x + y;
4    //...
5}

T1T2的类型需要在具体调用的时候才能进行模板初始化,在此之前无法得知其真实类型,如果此时不用auto来声明result的类型,函数就无法定义。

用于声明模板函数返回值类型

1template<typename T1, typename T2>
2auto Multiply(T1 x, T2 y) -> decltype(x * y) {
3    return x * y;
4}

当模板函数的返回值类型依赖于模板参数,也需要使用auto来声明返回值类型。此处的auto也称为返回值占位符,只是代表一个返回值类型的占位,真正的类型是后面的decltype语句。

这里不使用decltype(x * y) Multiply(T1 x, T2 y),是因为如果前置decltype语句,此时的xy还未声明,不能直接使用。

auto关键字的注意事项

auto变量定义时必须初始化

1auto a1 = 10; //ok
2auto a2; //error

auto关键字修饰

auto关键字可以结合constvolatile*&&&一起使用。

auto定义变量序列时必须始终推导为同一类型

1auto a1 = 10, b1 = 20, c1 = 30; //ok
2auto a2 = 10, b2 = 20.0, c2 = 'a'; //error

如果初始化表达式是引用

  • auto推导去除引用语义
1int a = 10;
2int& b = a;
3
4auto c = b; //c的类型推导为int,而非int&
  • auto&推导保留引用语义
1int a = 10;
2int& b = a;
3
4auto& d = b; //d的类型才是int&

如果初始化表达式带有const和volatile语义

  • auto推导去除constvolatile语义,除非显示声明
1const int a = 10;
2auto b = a; //b的类型推导为int,而非const int
3const auto c = a; //c的类型才是const int
  • auto&保留constvolatile语义
1const int a = 10;
2auto& b = a; //b的类型推导为const int&

这是因为如果auto推导的类型去除了const,那么b就变成了非const引用,可以修改a的值,这显然是错误的。

如果初始化表达式是数组

  • auto推导成指针类型
1int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
2auto brr = arr;
3std::cout << typeid(arr).name() << ", " << typeid(brr).name() << std::endl; //A10_i,Pi

其中A10_i表示int[10],而Pi表示int*

  • auto&推导为数组类型
1int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
2auto& brr = arr;
3std::cout << typeid(brr).name() << std::endl; //A10_i, A10_i

函数或模板参数不能声明为auto

1void func(auto param) { //error
2    //...
3}

auto仅是占位符,不是一个真正的类型

由于auto仅仅是代表占位,不是真正的类型,故不能对auto使用以类型为操作数的操作符,如sizeof()typeid()

Prev Post: 『C++用户定义字面量』
Next Post: 『C++列表初始化』