前言

这个东西在新版本的 C 语言中还是很常用的,尤其是用到 for 循环中。蒟蒻之前也是对这个了解不多,基本没用过(除非迫不得已,因为我的C++编译器太逊了,不支持此操作,用这个操作还得用在线 IDE,很麻烦),现在觉得有必要来整理整理了。

C++98 auto

早在C++98标准中就存在了auto关键字,那时的auto用于声明变量为自动变量,自动变量意为拥有自动的生命期,这是多余的,因为就算不使用auto声明,变量依旧拥有自动的生命期:

int a =10 ;  //拥有自动生命期
auto int b = 20 ;//拥有自动生命期
static int c = 30 ;//延长了生命期

C++98 中的 auto 多余且极少使用,C++11 已经删除了这一用法,取而代之的是全新的 auto:变量的自动类型推断。

C++11 auto

auto 可以在声明变量的时候根据变量初始值的类型自动为此变量选择匹配的类型,类似的关键字还有decltype。举个例子:

    int a = 10;
auto au_a = a;//自动类型推断,au_a为int类型
cout << typeid(au_a).name() << endl;

typeid运算符可以输出变量的类型。程序的运行结果输出了.

这种用法就类似于C#中的var关键字。auto的自动类型推断发生在编译期,所以使用auto并不会造成程序运行时效率的降低。而是否会造成编译期的时间消耗,我认为是不会的,在未使用auto时,编译器也需要得知右操作数的类型,再与左操作数的类型进行比较,检查是否可以发生相应的转化,是否需要进行隐式类型转换。

auto的用法

上面举的这个例子很简单,在真正编程的时候也不建议这样来使用auto,直接写出变量的类型更加清晰易懂。下面列举auto关键字的正确用法。

用于代替冗长复杂、变量使用范围专一的变量声明。

想象一下在没有auto的时候,我们操作标准库时经常需要这样:

#include<string>
#include<vector>
int main()
{
std::vector<std::string> vs;
for (std::vector<std::string>::iterator i = vs.begin(); i != vs.end(); i++)
{
//...
}
}

这样看代码写代码实在烦得很。有人可能会说为何不直接使用using namespace std,这样代码可以短一点。实际上这不是该建议的方法(C++Primer对此有相关叙述)。使用auto能简化代码:

#include<string>
#include<vector>
int main()
{
std::vector<std::string> vs;
for (auto i = vs.begin(); i != vs.end(); i++)
{
//..
}
}

for循环中的i将在编译时自动推导其类型,而不用我们显式去定义那长长的一串。

在定义模板函数时,用于声明依赖模板参数的变量类型。

template <typename _Tx,typename _Ty>
void Multiply(_Tx x, _Ty y)
{
auto v = x*y;
std::cout << v;
}

若不使用auto变量来声明v,那这个函数就难定义啦,不到编译的时候,谁知道x*y的真正类型是什么呢?

模板函数依赖于模板参数的返回值

template <typename _Tx, typename _Ty>
auto multiply(_Tx x, _Ty y)->decltype(_Tx*_Ty)
{
return x*y;
}

当模板函数的返回值依赖于模板的参数时,我们依旧无法在编译代码前确定模板参数的类型,故也无从知道返回值的类型,这时我们可以使用auto。格式如上所示。

decltype操作符用于查询表达式的数据类型,也是C++11标准引入的新的运算符,其目的也是解决泛型编程中有些类型由模板参数决定,而难以表示它的问题。

auto在这里的作用也称为返回值占位,它只是为函数返回值占了一个位置,真正的返回值是后面的decltype(_Tx*_Ty)。为何要将返回值后置呢?如果没有后置,则函数声明时为:

decltype(_Tx*_Ty)multiply(_Tx x, _Ty y)

而此时_Tx,_Ty还没声明呢,编译无法通过。

注意事项

  • auto 变量必须在定义时初始化,这类似于const关键字。

  • 定义在一个auto序列的变量必须始终推导成同一类型。例如:

    auto a4 = 10, a5 = 20, a6 = 30;//正确
auto b4 = 10, b5 = 20.0, b6 = 'a';//错误,没有推导为同一类型

使用auto关键字做类型自动推导时,依次施加一下规则:

  • 如果初始化表达式是引用,则去除引用语义。
    int a = 10;
int &b = a; auto c = b;//c的类型为int而非int&(去除引用)
auto &d = b;//此时c的类型才为int& c = 100;//a =10;
d = 100;//a =100;
  • 如果初始化表达式为const或volatile(或者两者兼有),则除去const/volatile语义。
    const int a1 = 10;
auto b1= a1; //b1的类型为int而非const int(去除const)
const auto c1 = a1;//此时c1的类型为const int
b1 = 100;//合法
c1 = 100;//非法
  • 如果auto关键字带上&号,则不去除const语意。
    const int a2 = 10;
auto &b2 = a2;//因为auto带上&,故不去除const,b2类型为const int
b2 = 10; //非法

这是因为如何去掉了const,则b2为a2的非const引用,通过b2可以改变a2的值,则显然是不合理的。

  • 初始化表达式为数组时,auto关键字推导类型为指针。
    int a3[3] = { 1, 2, 3 };
auto b3 = a3;
cout << typeid(b3).name() << endl;
  • 若表达式为数组且auto带上&,则推导类型为数组类型。
    int a7[3] = { 1, 2, 3 };
auto & b7 = a7;
cout << typeid(b7).name() << endl;
  • 函数或者模板参数不能被声明为auto
void func(auto a)  //错误
{
//...
}
  • 时刻要注意auto并不是一个真正的类型。auto仅仅是一个占位符,它并不是一个真正的类型,不能使用一些以类型为操作数的操作符,如sizeof或者typeid。
    cout << sizeof(auto) << endl;//错误
cout << typeid(auto).name() << endl;//错误

auto关键词的更多相关文章

  1. C/C++中的auto关键词

    C语言 auto被解释为一个自动存储变量的关键字,也就是申明一块临时的变量内存. 例如: auto double a=3.7; 表示a为一个自动存储的临时变量. C++语言 C++ 98标准/C++0 ...

  2. C++隐式推导-auto关键词

    总述 C++中有一个关键字,它不进行显式声明,而进行隐式推导,auto可以在声明变量时根据变量初始值的类型自动为此变量选择匹配的类型.C++语言类似的关键字还有decltype. 如何评价 C++ 1 ...

  3. C++11 auto and decltype

    1.auto关键字 C++新标准引入auto关键词,此auto与之前C语言的auto意义已经不一样了. 这里的auto是修饰未知变量的类型,编译器会通过此变量的初始化自动推导变量的类型. 例如:aut ...

  4. C++0X 学习之 auto

    auto并不是一个新关键词,是一个把旧关键词赋予新的作用,新的作用修饰变量声明,指示编译器根据变量的初始化表达式推导变量应有的类型.auto 声明的变量必须“在声明处完成初始化”,编译器才可根据初始化 ...

  5. C++ 14 auto

    C++14标准最近刚被通过,像以前一样,没有给这个语言带来太大变化,C++14标准是想通过改进C++11 来让程序员更加轻松的编程,C++11引入auto关键字(严格来说auto从C++ 03 开始就 ...

  6. linux进程的堆栈空间_代码段(指令,只读)、数据段(静态变量,全局变量)、堆栈段(局部变量)、栈【转】

    转自:http://blog.csdn.net/gongweijiao/article/details/8207333 原文参见:http://blog.163.com/xychenbaihu@yea ...

  7. C++ Primer 5th 第12章 动态内存

    练习12.1:在此代码的结尾,b1 和 b2 各包含多少个元素? StrBlob b1; { StrBlob b2 = {"a", "an", "th ...

  8. 【C和指针】笔记1

    数据 基本数据类型 整型家族:包含字符,短整型,整型和长整型 整型相互之间大小规定如下: 长整型至少和整型一样长,而整型至少应该和短整型一样长. short int至少16位,long int至少32 ...

  9. 与C/C++关键字extern有关的原理

    关键字有一定的语义,但是用法不唯一. 对于C/C++语言的预编译.编译.汇编.链接.我相信大家在接触C++一年不到就背的滚瓜烂熟,但是其中的细节,是后来才慢慢想明白的.为什么我不讲extern关键字呢 ...

  10. c++处理类型与自定义数据结构

    1.typedef 类型别名 有时我们在阅读c++程序时,发现一些未见过的类型,这实际上就是typedef导致的,使用很简单,如下: typedef int wayne; wayne a = , b ...

随机推荐

  1. vulnhub_me and my grilfriend

    解题步骤 主机nmap扫描,开放22和80端口 访问该ip,发现只能本地访问 查看源代码,提示需要使用x-forwarded-for的请求头,可以在burp suite中每次添加一个请求头,也可以使用 ...

  2. Wampserver64 报错:无法启动此程序,因为计算机中丢失 MSVCR110.dll。尝试重新安装该程序以解决此问题。

    缺少环境配置, 程序下载地址如下: https://www.microsoft.com/zh-cn/download/confirmation.aspx?id=30679 点击下载,下载完成后,双击程 ...

  3. word中查找替换不能使用 解决方案

    打开查找,然后点更多,最下面点不限定格式

  4. python-stack

    implements list deque LifoQueue 原文地址:https://realpython.com/how-to-implement-python-stack/ Argue lis ...

  5. 青少年CTF平台-Web-Flag在哪里

    平台名称:青少年CTF训练平台 题目名称:Flag在哪里? 解题过程: 启动环境,需要等待大概20秒左右的时间. 访问,页面显示Flag反正不在这. 右键网页,发现无法使用右键. 那么我们直接F12 ...

  6. 【路由器】OpenWrt 配置使用

    目录 Web 界面 汉化 root 密码 ssh 升级 LuCI 美化 锐捷认证 MentoHUST MiniEAP 防火墙 开放端口 端口转发 IPv6 USB 安装 USB 驱动 自动挂载 Ext ...

  7. 虾皮shopee根据ID取商品详情 API 返回值说明

    ​ item_get-根据ID取商品详情  注册开通 shopee.item_get 公共参数 名称 类型 必须 描述 key String 是 调用key(必须以GET方式拼接在URL中) secr ...

  8. TIKZ全局样式设置

    tikz绘图引擎 TIKZ绘图引擎是基于tex实现,代码极其复杂,每次编写都要单独设置样式,甚是繁琐,如何能够全局设置呢? \begin{tikzpicture}[ auto, % 决策结点 deci ...

  9. 【matplotlib 实战】--面积图

    面积图,或称区域图,是一种随有序变量的变化,反映数值变化的统计图表. 面积图也可用于多个系列数据的比较.这时,面积图的外观看上去类似层叠的山脉,在错落有致的外形下表达数据的总量和趋势.面积图不仅可以清 ...

  10. 树莓派3B/3B+的串口使用

    树莓派包含两个串口,一个称之为硬件串口(/dev/ttyAMA0),一个称之为mini串口(/dev/ttyS0).硬件串口由硬件实现,有单独的波特率时钟源,性能高.可靠.mini串口时钟源是由CPU ...