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运算符可以输出变量的类型。程序的运行结果输出了

int

这种用法就类似于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(x*y)
{
return x*y;
}

当模板函数的返回值依赖于模板的参数时,我们依旧无法在编译代码前确定模板参数的类型,故也无从知道返回值的类型,这时我们可以使用auto。格式如上所示。
decltype操作符用于查询表达式的数据类型,也是C++11标准引入的新的运算符,其目的也是解决泛型编程中有些类型由模板参数决定,而难以表示它的问题。
auto在这里的作用也称为返回值占位,它只是为函数返回值占了一个位置,真正的返回值是后面的decltype(_Tx*_Ty)。为何要将返回值后置呢?如果没有后置,则函数声明时为:

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

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

注意事项

  • 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;

    程序将输出

    int *

  • 若表达式为数组且auto带上&,则推导类型为数组类型。

    int a7[3] = { 1, 2, 3 };
    auto & b7 = a7;
    cout << typeid(b7).name() << endl;

    程序输出

    int [3]

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

    void func(auto a)  //错误
    {
    //...
    }
  • 时刻要注意auto并不是一个真正的类型。
    auto仅仅是一个占位符,它并不是一个真正的类型,不能使用一些以类型为操作数的操作符,如sizeof或者typeid。

    cout << sizeof(auto) << endl;//错误
    cout << typeid(auto).name() << endl;//错误

C++ auto 关键字的使用的更多相关文章

  1. 初学C++ 之 auto关键字(IDE:VS2013)

    /*使用auto关键字,需要先赋初值,auto关键字是会根据初值来判断类型*/ auto i = ; auto j = ; cout << "auto i = 5" & ...

  2. C++11 - 类型推导auto关键字

    在C++11中,auto关键字被作为类型自动类型推导关键字 (1)基本用法 C++98:类型 变量名 = 初值;   int i = 10; C++11:auto 变量名 = 初值;  auto i ...

  3. C++11特性:auto关键字

    前言 本文的内容已经不新鲜了.关于auto,翻来覆去被人知道的都是这些东西,本文并没有提出新颖的auto用法. 本人原是痛恨博客一篇篇都是copy而来缺乏新意的探索,当然,本文不是copy而来,但发布 ...

  4. 你好,C++(11)如何用string数据类型表示一串文字?根据初始值自动推断数据类型的auto关键字(C++ 11)

    3.5.2  字符串类型 使用char类型的变量我们可以表示单个字符,那么,我们又该如何表示拥有多个字符的字符串呢? 我们注意到,一个字符串是由多个字符串连起来形成的.很自然地,一种最简单直接的方法就 ...

  5. auto关键字使用

    auto类型变量--根据初始值推断真实的数据类型. 有些时候并不能很确定一个变量应该具备的数据类型,例如:将一个复杂表达式的值赋给某个变量,此时并不能很明显的确定这个值所具备的数据类型.此时auto关 ...

  6. 【C++11新特性】 auto关键字

    原文链接: http://blog.csdn.net/xiejingfa/article/details/50469045 熟悉脚本语言的人都知道,很多脚本语言都引入了“类型自动推断”技术:比如pyt ...

  7. C++ 11 auto关键字

    熟悉脚本语言的人都知道,很多脚本语言都引入了“类型自动推断”技术:比如Python,可以直接声明变量,在运行时进行类型检查.随着C++11标准的发布,C++语言也引入了类型自动推断的功能,这就是我们今 ...

  8. 关于C/C++中的“auto”关键字

    C/C++ 98标准 C++03标准 早在C++98标准中就存在了auto关键字,那时的auto用于声明变量为自动变量,自动变量意为拥有自动的生命期.此用法是多余的,因为即使定义变量时不加" ...

  9. C++初阶(命名空间+缺省参数+const总结+引用总结+内联函数+auto关键字)

    命名空间 概述 在C/C++中,变量.函数和后面要学到的类都是大量存在的,这些变量.函数和类的名称将都存在于全局作用域中,可能会导致很多冲突.使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲 ...

随机推荐

  1. JavaScript中标识符的命名

    JavaScript中的标识符的命名有以下规则: 由字母.数字.$._组成 以字母.$._开头 不可以使用保留字!!! 要有意义!!!!!!! 标识符的命名规范: 1.驼峰命名法 除标识符的第一个单词 ...

  2. 对"某V皮"N服务器节点的一次后渗透测试

    i春秋作家:jasonx 前言:由于这个VPN节点服务器是之前拿到的,一直没时间做进一步渗透,昨天看到我蛋总表哥发红包,然后我运气爆表抢了个运气王,再加上好久没发文章了,所以就抽空测试下咯. 0×01 ...

  3. Hi,我们再来聊一聊Java的单例吧(转)

    1. 前言 单例(Singleton)应该是开发者们最熟悉的设计模式了,并且好像也是最容易实现的——基本上每个开发者都能够随手写出——但是,真的是这样吗? 作为一个Java开发者,也许你觉得自己对单例 ...

  4. WebDriver高级应用实例(8)

    8.1使用Log4j在测试过程中打印日志 目的:在测试过程中,使用Log4j打印日志,用于监控和后续调试测试脚本 被测网页的网址: http://www.baidu.com 环境准备: (1)访问ht ...

  5. [视频]K8飞刀 ms15022 office漏洞演示动画

    [视频]K8飞刀 ms15022 office漏洞演示动画 https://pan.baidu.com/s/1eQnV8qQ

  6. 关于oracle RAC心跳线采用直连 还是交换机连接的建议

    关于oracle RAC心跳线的连接方式,各个论坛,包括网上文章的说法是:官方说是不建议直连,建议采用交换机连接的方式!PS:但是,一直没有找到官方文档的出处,有知道的兄弟,烦请评论区提供下地址!!! ...

  7. python中文画图显示乱码解决办法

    最近使用notebook Python中的matplotlib作图,发现中文设置的坐标标签和title都显示为乱码,用了网上的许多教程都不管用,嘴后解决的方式是设置下述的两行即可搞定: plt.rcP ...

  8. Install vsftpd on centos

    安装vsftpd程序. sudo yum -y install vsftpd 启动ftp服务. sudo service vsftp start 添加ftp用户,并设置密码. sudo useradd ...

  9. node.js的

    node.js入门 http://www.cnblogs.com/rubylouvre/archive/2010/07/15/1778403.html 专题:Node.js专区http://devel ...

  10. Android 安装时报错INSTALL_FAILED_NO_MATCHING_ABIS 的解决办法

    $ adb push D:\AndroidstudioTestWorkSpace\app\build\outputs\apk\app-debug.apk       /data/local/tmp/c ...