const 引用的分析
const 引用:
在初始化常量引用时,允许用任意表达式作为初始值,只要该表达式的结果能转换成引用的类型即可。尤其,允许为一个常量引用绑定非常量的对象、字面值,甚至是一个表达式。我们来看 const 引用的分析:
- #include <iostream>
- int main(int argc, char* argv[])
- {
- const int &i = ;
- return ;
- }
该代码的汇编代码如下:
- int main(int argc, char* argv[])
- {
- 00964C80 push ebp
- 00964C81 mov ebp,esp
- 00964C83 sub esp,0D8h
- 00964C89 push ebx
- 00964C8A push esi
- 00964C8B push edi
- 00964C8C lea edi,[ebp-0D8h]
- 00964C92 mov ecx,36h
- 00964C97 mov eax,0CCCCCCCCh
- 00964C9C rep stos dword ptr es:[edi]
- const int &i = ;
- 00964C9E mov dword ptr [ebp-14h],0Ch
- 00964CA5 lea eax,[ebp-14h]
- 00964CA8 mov dword ptr [i],eax
- return ;
- 00964CAB xor eax,eax
- }
我们可以看到,const 引用绑定一个12的时候,相当于有如下的步骤:
int temp = 12;
const int &i = temp;
我们上面分析过,引用实质上是一个指针,绑定一个对象就是保存对象的地址,那么一个12是没有地址的,所以需要一个临时变量。当然如果那个常量本身有地址,那么久直接将其地址保存到引用的内存空间。
下面考虑一个常量引用绑定到另一种类型时发生了什么:
- int main(int argc, char* argv[])
- {
- double num = 23.2;
- const int &i = num;
- return ;
- }
汇编结果:
- double num = 23.2;
- 000E436E movsd xmm0,mmword ptr ds:[0ECD80h]
- double num = 23.2;
- 000E4376 movsd mmword ptr [num],xmm0
- const int &i = num;
- 000E437B cvttsd2si eax,mmword ptr [num]
- 000E4380 mov dword ptr [ebp-24h],eax
- 000E4383 lea ecx,[ebp-24h]
- 000E4386 mov dword ptr [i],ecx
- return ;
- 000E4389 xor eax,eax
- }
我们可以看到,这里也是生成了一个临时变量,步骤相当于如下:
const int temp = num;
const int &i = temp;
所以,如果 i 不是常量引用,那么就应该允许对 i 所绑定的对象进行修改,但是 temp 是一个临时变量,明显是一个右值,不合法。
当然,如果是这样的代码
- int main(int argc, char* argv[])
- {
- const int num = ;
- const int &i = num;
- return ;
- }
那么就不需要一个中间变量。
于是这里就出现了一个很有趣的问题,当一个 const 引用绑定一个非常量对象的时候,其行为可能是不同的,比如如下:
- int main(int argc, char* argv[])
- {
- double num = 23.9;
- const int &i = num;
- num = 54.9;
- cout << i << endl;
- return ;
- }
这份代码的结果是:23
而下面这份:
- int main(int argc, char* argv[])
- {
- int num = ;
- const int &i = num;
- num = ;
- cout << i << endl;
- return ;
- }
结果是 54. 就是因为上面那份生成了一个中间变量的原因。
所以在使用 const 引用绑定非 const 变量的时候要注意这个问题。
const 引用的分析的更多相关文章
- C++ Const引用详解
(1) 在实际的程序中,引用主要被用做函数的形式参数--通常将类对象传递给一个函数.引用必须初始化. 但是用对象的地址初始化引用是错误的,我们可以定义一个指针引用. 1 int ival ...
- C++引用和const引用、常量指针、指针常量
1.引用.常量引用 引用主要被用做函数的形式参数--通常将类对象传递给一个函数. 引用在内部存放的是一个对象的地址,它是该对象的别名.引用不占用内存,因为取地址引用的值和被引用变量的地址相同.但是ob ...
- 临时变量不能作为非const引用
转自:http://blog.csdn.net/u011068702/article/details/64443949 1.看代码 2.编译结果 3.分析和解决 就拿f(a + b)来说,a+b的值会 ...
- C++ const引用
(1) 在实际的程序中,引用主要被用做函数的形式参数--通常将类对象传递给一个函数.引用必须初始化. 但是用对象的地址初始化引用是错误的,我们可以定义一个指针引用. 1 int ival ...
- 【c++基础】const、const指针、const引用
一.const常量 声明时必须同时初始化(和“引用”一样) 二.const指针 三.const引用 引用本身和引用的对象都是const对象,可以用字面值来赋给const引用(普通引用则不行) ; co ...
- 传const引用代替传值
1.为什么使用传const引用? a.被调方法中,形参不再进行copy构造,以及析构,提高效率. b.传值,会出现对象切割的问题. 2.有没有例外? 在编译器底层,引用是使用指针实现的.这就意味着,如 ...
- python的引用计数分析(二)
python所有对象引用计数被减少1的情况: 一.对象的别名被赋予新的对象; a = 23345455 # 增加了一个引用 b = a # 增加了一个引用 print(sys.getrefcount( ...
- const引用
在C++中可以声明const引用 const Type& name = var: const引用让变量拥有只读属性 const int &a = b const int &a ...
- c/c++ 拷贝控制 右值与const引用
拷贝控制 右值与const引用 背景:当一个函数的返回值是自定义类型时,调用侧用什么类型接收?? 1,如果自定义类型的拷贝构造函数的参数用const修饰了:可以用下面的方式接收. Test t2 = ...
随机推荐
- BZOJ4000 TJOI2015棋盘(状压dp+矩阵快速幂)
显然每一行棋子的某种放法是否合法只与上一行有关,状压起来即可.然后n稍微有点大,矩阵快速幂即可. #include<iostream> #include<cstdio> #in ...
- JavaScript-序列化及转义
1. for循环: while循环: 2. 条件语句: 类似于if else的功能. name='1'; switch(name){ case:'1': console.log(123); brea ...
- Javascript 中 == 和 === 区别是什么?
Javascript 中 == 和 === 区别是什么? 作者:Belleve链接:https://www.zhihu.com/question/31442029/answer/77772323来源: ...
- Android 数据库升级中数据保持和导入已有数据库
一.数据库升级: 在我们的程序中,或多或少都会涉及到数据库,使用数据库必定会涉及到数据库的升级,数据库升级带来的一些问题,如旧版本数据库的数据记录的保持,对新表的字段的添加等等一系列问题,还记得当我来 ...
- React setState和修改props触发的钩子
1. setState的改变会触发4个生命周期钩子 shouldComponentUpdatecomponentWillUpdaterendercomponentDidUpdate 2. props的 ...
- git生成ssh key和多账号支持
git配置ssh 1.首先设置git的全局user name和email $ git config --global user.name "ygtzz"$ git config - ...
- 【BZOJ 3569】DZY Loves Chinese II 随机化+线性基
用到一个结论——[先建树,再给每个非树边一个权值,每个树边的权值为覆盖他的非树边的权值的异或和,然后如果给出的边存在一个非空子集异或和为0则不连通,否则连通](必须保证每条边的出现和消失只能由自己产生 ...
- ContextLoaderListener和Spring MVC中的DispatcherServlet加载内容的区别【转】
原文地址:https://blog.csdn.net/py_xin/article/details/52052627 ContextLoaderListener和DispatcherServlet都会 ...
- Linux下 ps -ef 和 ps aux 的区别及格式详解
原文:https://www.cnblogs.com/5201351/p/4206461.html Linux下ps -ef和ps aux的区别及格式详解 Linux下显示系统进程的命令ps,最常用的 ...
- Codeforces Round #401 (Div. 2) A B C 水 贪心 dp
A. Shell Game time limit per test 0.5 seconds memory limit per test 256 megabytes input standard inp ...