这篇文章的起因是下面这两段代码,出自《C++ primer 5th》中文版P62页:

auto &h =42;//错误,不能为非常量引用绑定字面值

const auto &j =42;//正确,可以为常量引用绑定字面值

一开始看到auto时,我认为不存在错误的auto语句,因为auto就是根据右值类型来匹配一个适当的类型给左值~

结果这里居然错了!我很诧异,仔细看了看是const引起的,那么问题来了,为什么必须要加const才能识别42是一个const int&?

百度了一下,找到一个知乎的回答:

https://www.zhihu.com/question/36052573?utm_source=qq&utm_medium=social

感觉里面的问题描述和我想的一样,回答里说的却没有我想要的答案:为什么必须是const引用才能绑定字面值?有什么原因么?

我又去stack overflow提问,因为英文太差,问题描述不能很好的写出来:

https://stackoverflow.com/questions/46461946/cannot-bind-a-plain-reference-to-a-literal/46464445#46464445

误打误撞,又纠正了我一些概念上的问题,接下来我来总结一下。有些东西后面学到了才用到,我会点到即止,留下问题的可能答案以后看。

首先是文章开头那两段代码,为什么第一段错第二段对?

这里要明确几个概念:

(1)编译器先判断右值的类型,再决定左值的类型,而不是先定义左值的类型再进行绑定的操作......
(2)const 引用可以绑定字面值,而且auto引用和指针变量在绑定或赋值操作时是保留底层const属性的,而一般情况下是忽略顶层const属性,才需要人为添加const来声明顶层const属性。

(1、2改动自楼上第一个知乎答案里的问题描述)

(3)auto不能推断const,其默认只保留顶层const(这里和2有雷同,但为了完整我还是写出来了);非常量左值引用不能绑定到纯右值上。

(3是上面stack overflow中问题的回答理解,截图见下面)

这里补几个专业词汇:

pure rvalue=prvalue=纯右值         lvalue=left value=左值           rvalue=right value=右值

这三者有什么区别的?我觉得这个问题里很多回答说的很好:

https://www.zhihu.com/question/39846131/answer/85277628

简单的总结,就是有地址的就是左值,没有就是右值,至于里面提到的纯右值、右值引用概念,现在没必要深究,先放着,以后学到了再说,可以参考的文章有:

http://blog.csdn.net/ylbs110/article/details/51106164(我也不知道这篇文章质量如何,以后用到再说)

最后,再重新强调几个东西,基本数据类型、限定符、声明符列表是不一样的东西!int、double等是基本数据类型,const是限定符,声明符列表包括名字和修饰符,名字就是对象名字,修饰符有*和&(目前学到的只有这两个),而auto是类型说明符,换句话说,他只能表示或者替代基本数据类型!这也是为什么const我们要自己视情况加,auto并不能帮我们确定的原因————auto是一个类型说明符,其只能代替基本类型的位置,不能代替限定符const和类型修饰符&、*之流。

好了,准备工作都弄好了,现在可以试着解释上面的问题了。

首先是第一段代码。

auto
&h =42;//错误,不能为非常量引用绑定字面值

这段代码执行流程是这样的:

编译器会先判断右值的类型:“42”是一个int的字面值。

字面值里只有char类才有地址,其余都是右值!(左值是等号两边都可以放的,右值只能放等号右边,有地址的才是左值,否则是右值,姑且这样认为先),所以,这里的42是一个int型的右值。

编译器判断出这是一个int后,auto就等价于int了(注意,没有*没有&没有const,就只是等价于一个基础数据类型)

也就是说上面那段等价于:

Int &h =42;

这是一个绑定int型的引用,而规定是引用不能绑定一个纯右值,所以这里错了————我也不知道为什么,这里似乎牵扯到生命周期、纯右值,没学到,以后再说,可以参考的文章有:

https://stackoverflow.com/questions/39718268/why-do-const-references-extend-the-lifetime-of-rvalues

明白了这段代码哪里错,就能理解文章开头的第二段代码为什么对了——先死记吧,以后再说。

至此这个疑问就告一段落了,最后说一说这次查资料中自己纠正的一个错误概念:

等号两边的类型是一样的否则怎么能赋值呢。

明白上面这句话是错的,源自于上面我在stack overflow中提问的一个回答:

最后,我想强调一下auto定义的变量必须有初始值,而这正是有了他还要再有一个decltype类型指示符的原因。

有了auto是不是不需要显示声明类型了?————见:https://www.zhihu.com/question/35517805/answer/63304992

这个解释没看懂,以后再看

(2)左右值初探与auto类型说明符的更多相关文章

  1. auto类型说明符的注意事项

    1.auto类型说明符,是C++11标准下的,它能让编译器自行判断表达式的类型. 2.auto也能在一条语句上声明多个变量,但是,该语句上的多个变量的类型,必须一致. 3.编译器推断出来auto类型可 ...

  2. C++11 auto类型说明符的使用

    编程的时候常常需要把表达式的值赋给变量,这就要求在声明变量的时候清楚地知道表达式的类型.然而做到这一点很难,有时候根本做不到.为了解决这个问题.C++11新标准引入了auto类型说明符,用它就 能让编 ...

  3. C++ auto类型说明符

    本系列文章由 @yhl_leo 出品,转载请注明出处. 文章链接: http://blog.csdn.net/yhl_leo/article/details/50864612 编程时常常需要把表达式的 ...

  4. auto类型说明符

    auto让编译器通过出初始值来推算变量的类型,显然,auto定义的变量必须有初始值: //由val1和val2相加的结果可以推断出item的类型 auto item = val1 + val2;//i ...

  5. C++通过迭代修改字符串本身(auto类型说明符)

    以字符串这种支持 for (declaration : expression) statement 这样for语句迭代的数据结构为例,我们看看auto关键字在类型推断中的作用. string s = ...

  6. C++ decltype类型说明符(尾置返回类型使用)

    转自https://blog.csdn.net/yhl_leo/article/details/50865552 1 基本语法 decltype 类型说明符生成指定表达式的类型.在此过程中,编译器分析 ...

  7. C++ decltype类型说明符

    本系列文章由 @yhl_leo 出品,转载请注明出处. 文章链接: http://blog.csdn.net/yhl_leo/article/details/50865552 1 基本语法 declt ...

  8. Effective Modern C++翻译(3)-条款2:明白auto类型推导

    条款2 明白auto类型推导 如果你已经读完了条款1中有关模板类型推导的内容,那么你几乎已经知道了所有关于auto类型推导的事情,因为除了一个古怪的例外,auto的类型推导规则和模板的类型推导规则是一 ...

  9. 现代C++之理解auto类型推断

    理解auto类型推断 上一篇帖子中讲述了模板类型推断,我们知道auto的实现原理是基于模板类型推断的,回顾一下模板类型推断: template <typename T> void f(Pa ...

随机推荐

  1. zabbix学习系列之基础概念

    触发器 概念 "监控项"仅负责收集数据,而通常收集数据的目的还包括在某指标对应的数据超出合理范围时给相关人员发送警告信息,"触发器"正式英语为监控项所收集的数据 ...

  2. 安装eclipse中html/jsp/xml editor插件以及改动html页面的字体

    近期在做android项目,用到了jquery mobile 框架以及phonegap,所以就会涉及一些html文件,可是html文件打开的方式是Text Editor ,而且打开之后一些html代码 ...

  3. Mycat(5):聊天消息表数据库按月分表实践,平滑扩展

    本文的原文连接是: http://blog.csdn.net/freewebsys/article/details/47003577 未经博主同意不得转载. 1,业务需求 比方一个社交软件,比方像腾讯 ...

  4. ExtJS学习--------Ext.Element中其它操作方法学习

    (1)对齐操作 (2)尺寸操作 (3)定位操作 (4)滚动操作 (5)经常使用事件方法

  5. convex hull

    1 什么是convex hull 就是凸包,是计算几何中的一个概念,计算几何是计算机图形学的基础之一. 对于二维平面来说是这样的:对于二维平面上的点集,凸包是位于最外层的点构成的包围其它所有的点的凸多 ...

  6. ubuntu将mysql、nginx添加到环境变量中

    vim /etc/profile 添加 export PATH="$PATH:/usr/local/mysql/bin" export PATH="$PATH:/usr/ ...

  7. python-----自动解压并删除zip文件

    如何自动解压并删除zip? 如何解压  →  使用内置模块来实现(shutil.unpack_archive) 如何删除zip  →  使用内置模块os来实现(os.remove) 如何监测zip的出 ...

  8. Java IO --ByteArrayOutputStream (六)***

    Java提供了很丰富的io接口,已经可以满足我们大部分读取数据的需求,这个在C读取数据需要自己定义缓冲区数组大小,而且要小心翼翼的防止缓冲区溢出的情况相当不同.一般情况下我们读取的数据都是直接读取成为 ...

  9. 7. ExtJS.form中msgTarget

    转自:https://www.cnblogs.com/guafuli/articles/msgtarget_values.html Ext表单提示方式:msgTarget:有4中方式:qtip,tit ...

  10. 谈CSS布局中HTML标签语义化

    很多人都在做前端,当然这里包括很多新手,也许在新手的想法就是在做布局的时候不要用font标签之类的就算是web标准了,这样一来,造成如今网上“div泛滥”,一看源文件,霍,除了div没其他标签了. 这 ...