C++中auto关键字的使用

C++中auto关键字的使用


写在前面:

作者是一个新手,文章中的内容大部分来自于其他博文,作者仅仅是加入了少量自己的理解,方便自己在遗忘时查看,并且作者会在文章末尾附上原文链接,方便各位网友前往学习


1 auto关键字简介

在C中,使用auto修饰的变量,是具有自动储存器的局部变量,但是很少有人去使用它,在C++11中,auto有了新的含义,他不再是是个储存类型指示符,而是作为一个新的类型指示符来指示编译器,auto声明的变量必须由编译器在编译时期推导而得.

#include 

using namespace std;

double ReturnDouble() {
	return 3.14;
}

int main() {
	int a = 10;
	auto b = a;
	auto c = 'a';
	auto d = ReturnDouble();

	cout << typeid(a).name() << endl;
	cout << typeid(b).name() << endl;
	cout << typeid(c).name() << endl;
	cout << typeid(d).name() << endl;
	return 0;
}

输出如下:C++中auto关键字的使用_第1张图片

注意:auto是一个占位符,编译器会根据初始化来推演出类型,填充位置,所以auto必须初始化

比如:

auto a;//不行,不知道a是什么类型
auto b=10;//可以,根据10推测出是int类型

C++中auto类似于C#中的var;

2 使用细则

  1. 使用auto来声明指针的时候,使用auto和auto没有区别

  2. 使用auto来声明引用类型的时候必须加"&"

    #include 
    
    using namespace std;
    
    double ReturnDouble() {
    	return 3.14;
    }
    
    int main() {
    	int a = 10;
        
    	auto ra1 = a;
    	auto& ra2 = a;
    
    	cout << &a << endl;
    	cout << &ra1 << endl;//ra1仅仅是简单的赋值;
    	cout << &ra2 << endl;//ra2引用了a,和a等价,且使用同一个内存空间;
    	return 0;
    }
    

    运行结果如下:
    C++中auto关键字的使用_第2张图片

  3. 当同一行声明多个变量时,类型必须相同,否则会报错

    auto a=1,b=10;//可行
    auto b=10,c='a';//报错
    

    详细理解auto的推演:

    const auto *v=&x,u=6;
    

    执行成功,v是"const int*"类型,而u是"const int"类型.

    v和u在同一行声明,为什么可以是不同的类型呢?

    原因如下:

    在"const auto*v=&x"的时候,编译器确定了auto的类型为int,所以到了u的时候,就是"const int"而不是"const int*".即auto推测的不是变量的数据类型,而是变量中auto作为占位符应该替换的类型.

    注意事项:

    1. 虽然经过了"const auto *v=&x"的推导,auto的类型确定为int,但是u必须写后面的"=6",即仍然需要初始化
    2. u的初始化不能让编译器推导产生二义性,比如:“u=6.0"编译器会报错,因为在u处推导得到"double"而在*v处推导得到"int”,两个互相矛盾

    由上面的例子可以看出来,auto不能代表一个实际的类型声明,只是一个类型声明在编写代码阶段的"占位符",在使用auto变量时必须立刻初始化,让编译器立刻推断出他的实际类型,并在编译阶段将auto占位符替换为真正的类型.

3 auto推演失败的情况

  1. auto不能作为函数的参数

    1. 无法作为参数列表
    2. 无法作为返回值类型

C++中auto关键字的使用_第3张图片

  1. auto不能用来声明数组

    OutPut

  2. 为了避免和C++98中的auto发生混淆,C++11仅保留了auto作为类型指示符的用法,只是一个占位符

  3. auto不能定义类的非静态成员变量

C++中auto关键字的使用_第4张图片

  1. 实例化模板时不能使用auto作为模板参考
void func(auto a = 1) {}          // error: auto不能用于函数参数
struct Foo
{
    auto var1_ = 0;               // error: auto不能用于非静态成员变量
    static const auto var2_ = 0;  // OK: var2_ -> static const int
};
template 
struct Bar {};

int main(void)
{
    int arr[10] = {0};
    auto aa     = arr;   // OK: aa -> int *
    auto rr[10] = arr;   // error: auto无法定义数组
    Bar bar;
    Bar bb = bar;  // error: auto无法推导出模板参数
    return 0;
}

4 新式for循环

#include 

using namespace std;

int main() {
	int array[] = { 1,2,3,4,5,6 };
	for (auto i:array)
	{
		cout << i << "  ";
	}
	return 0;
}

输出如下:在这里插入图片描述

注意事项:

  1. 对于数组而言,数组中第一个元素和第二个元素就是范围,对于类而言,应该提供begin和end的方法,begin和end就是for循环的迭代的范围;
  2. 迭代的对象要实现++和==的操作;

5 auto的推导规则

​ auto除了可以和指针,引用一起用,还可以和cv限定符(cv-qualifier,const和volatile限定符的统称)一起使用.

举例如下:

int x = 0;
auto * a = &x;      // a -> int*,auto被推导为int
auto   b = &x;      // b -> int*,auto被推导为int*
auto & c = x;       // c -> int&,auto被推导为int
auto   d = c;       // d -> int ,auto被推导为int
const auto e = x;   // e -> const int
auto f = e;         // f -> int
const auto& g = x;  // e -> const int&
auto& h = g;        // f -> const int&

上面的例子告诉我们:

  • a和c的推导结果很简单,auto在编译时被替换成int,所以a的类型是"int*“,c的类型是"int&”
  • b的推导结果说明,哪怕auto在声明的时候不声明为指针类型,也可以推导出指针类型
  • d的推导结果说明,当表达式是一个引用类型的时候,auto会自动把引用类型抛弃,直接还原成原始类型int
  • e的推导结果说明,const auto在编译的时候会被替换为const int;
  • f的推导结果说明,当表达式带有const(实际上volatile也会有相同的结果)属性时,auto会摆const属性抛弃掉,推导成"non-const类型int"
  • g,h的推导结果说明,当auto和引用(指针也可以)一起使用的时候,auto的推导保留表达式的const;

那么总结如下:

  1. 当不声明为指针或者引用时,auto的推导结果和初始化表达式抛弃引用和cv限定符后类型一致;
  2. 当声明为指针或者引用的时候,auto的推导结果将保持初始化表达式的cv属性.

6 什么时候使用auto

  1. 迭代器变量的定义过程过于繁琐,可以通过auto来简化

    原来:std::map::iterator it = resultMap.begin();

    现在:auto it = resultMap.begin();

  2. 在unordered_multimap中查找一个范围

    原来:std::pair< std::unordered_multimap::iterator, std::unordered_multimap::iterator > range = resultMap.equal_range(key);

    现在:auto range = map.equal_range(key);

  3. 当我们不知道变量应该被定义成什么类型时

参考文章:

C++ auto(类型推导)精讲 (biancheng.net)

auto关键字_心文花雨的博客-CSDN博客_auto关键字

你可能感兴趣的:(c++)