(2)左右值初探与auto类型说明符
这篇文章的起因是下面这两段代码,出自《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类型说明符的更多相关文章
- auto类型说明符的注意事项
1.auto类型说明符,是C++11标准下的,它能让编译器自行判断表达式的类型. 2.auto也能在一条语句上声明多个变量,但是,该语句上的多个变量的类型,必须一致. 3.编译器推断出来auto类型可 ...
- C++11 auto类型说明符的使用
编程的时候常常需要把表达式的值赋给变量,这就要求在声明变量的时候清楚地知道表达式的类型.然而做到这一点很难,有时候根本做不到.为了解决这个问题.C++11新标准引入了auto类型说明符,用它就 能让编 ...
- C++ auto类型说明符
本系列文章由 @yhl_leo 出品,转载请注明出处. 文章链接: http://blog.csdn.net/yhl_leo/article/details/50864612 编程时常常需要把表达式的 ...
- auto类型说明符
auto让编译器通过出初始值来推算变量的类型,显然,auto定义的变量必须有初始值: //由val1和val2相加的结果可以推断出item的类型 auto item = val1 + val2;//i ...
- C++通过迭代修改字符串本身(auto类型说明符)
以字符串这种支持 for (declaration : expression) statement 这样for语句迭代的数据结构为例,我们看看auto关键字在类型推断中的作用. string s = ...
- C++ decltype类型说明符(尾置返回类型使用)
转自https://blog.csdn.net/yhl_leo/article/details/50865552 1 基本语法 decltype 类型说明符生成指定表达式的类型.在此过程中,编译器分析 ...
- C++ decltype类型说明符
本系列文章由 @yhl_leo 出品,转载请注明出处. 文章链接: http://blog.csdn.net/yhl_leo/article/details/50865552 1 基本语法 declt ...
- Effective Modern C++翻译(3)-条款2:明白auto类型推导
条款2 明白auto类型推导 如果你已经读完了条款1中有关模板类型推导的内容,那么你几乎已经知道了所有关于auto类型推导的事情,因为除了一个古怪的例外,auto的类型推导规则和模板的类型推导规则是一 ...
- 现代C++之理解auto类型推断
理解auto类型推断 上一篇帖子中讲述了模板类型推断,我们知道auto的实现原理是基于模板类型推断的,回顾一下模板类型推断: template <typename T> void f(Pa ...
随机推荐
- node使用npm一句命令停止某个端口号 xl_close_port
一命令停止某一个端口号,再也不怕端口号被占用了.. 1.插件背景 开启项目的时候,跑不起来了? 很多时候的原因就是,依赖版本,依赖的包未安装,再就是端口号被占用 例如: 这时候,我们做法就是: 1.到 ...
- 模拟用户点击弹出新页面不会被浏览器拦截_javascript技巧
原文:http://www.html5cn.com.cn/article/zxzx/3195.html 相信用过window.open的小伙伴们都遇到过被浏览器拦截导致页面无法弹出的情况:我们换下思路 ...
- [教程] NETGEAR R7800 路由器TFTP刷机方法(适用于.img格式固件各种刷)
本教程是我参照R7800的OP/LEDE固件交流群内文件做的教程,可以说是完善.补充吧. 本帖适用于:① 原厂固件刷原厂固件:② 原厂固件刷第三方固件(.img格式):③ 第三方固件刷回原厂固件(.i ...
- ViewFlipper实现ViewPager的页面切换效果
activity_main.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android&qu ...
- SpringBoot 基于jjwt快速实现token授权
1.添加maven依赖注解 <!--JJWT库--> <dependency> <groupId>io.jsonwebtoken</groupId> & ...
- java List.add操作可以指定位置
java List.add操作可以指定位置,addAll也可以指定: 使用: public class Test02 { public static void main(String[] args) ...
- VM虚拟机的网卡模式介绍
(1)Bridged方式 用这种方式,虚拟系统的IP可设置成与本机系统在同一网段,虚拟系统相当于网络内的一台.独立的机器,与本机共同插在一个Hub上,网络内其他机器可访问虚拟系统,虚拟系统也可访问网络 ...
- AutoCAD如何设置线宽
一般要求粗实线粗实线0.4,细实线0.2mm. 1 先打开图层特性管理器,新建一个图层,专门放粗实线(我起名叫"我的粗实线",颜色设置为紫色,线宽为0.4mm),此前的乱七八糟的图 ...
- 【Android】应用安全——反编译
用java开发最操心的就是得到反编译,所以作为开发人员我们须要知道怎么反编译,那样才干知道怎样防止反编译.保证代码安全. 以下来看下比較经常使用的方法! 第一种方式:利用apktool反编译 1,首先 ...
- 打开与关闭Linux防火墙
1) 重启后生效 开启: chkconfig iptables on 关闭: chkconfig iptables off 2) 即时生效,重启后失效 开启: service iptables sta ...