这也算是一个老生常谈的问题,写这个其实就是想趁着暑假把博客丰富一下。

咱随便在谷哥、度娘、病软引擎上搜搜都可以得到各种关于引用的解释,无非就是“引用不同于指针,引用是一个变量的别名”“使用引用就是使用变量本身”“”等等这些,于是大量的概念轰炸下,“引用不占用空间”这一言论貌似也是到处都有,流传甚广,几近泛滥,已经有淹没真想之势。于是本着追逐真理之精神,把引用究竟占不占空间这事儿解释清楚,至于引用与指针是不是不同的东西,这一哲学问题见仁见智,咱们就不去探究,真想搞清楚还是得问C++的爸爸。

真要搞清楚,还得从代码本身出发。

  1. int main()
  2. {
  3. int a=10;
  4. int* b=&a;
  5. a=30;
  6. *b=20;
  7. }

先看看这段代码有什么意义?是不是觉得没有什么意义?嗯,确实没什么意义,从表面上也完全看不出什么来,当然了,如果您看出什么来了,那您一定要当什么都没看出来!

好了,要想知道这段代码做了什么,还得从汇编看起,毕竟从底层看起能都尽量多地绕过编译器,展示其真实行为,不失为一个学习基本概念的好办法。因为我用的是linux平台,所以我比较倾向于用AT&T汇编展示,如果您不熟悉,完全没关系,赶紧关掉网页,麻溜走人!。。。。。英雄留步,我这儿跟你开个玩笑活跃一下气氛,诶,诶,那位爷,能别抄起凳子么?

  1. subl $16, %esp //分配空间
  2. call ___main
  3. movl $10, 8(%esp) //把10存入变量a代表的空间
  4. leal 8(%esp), %eax //将变量a的地址存入寄存器eax
  5. movl %eax, 12(%esp) //将变量a的地址存入另一块儿地址,这里即指针b
  6. movl $30, 8(%esp) //将30赋值给变量a
  7. movl 12(%esp), %eax //将变量a的地址赋值给寄存器eax
  8. movl $20, (%eax) //将20赋值给寄存器eax的值所代表的地址处,

通过注释(应该还算清晰吧),可以完整对应上面那段代码的行为,这里可以真切地从肌肤与体位上感受到其行为的确定性。可以看到,一切都在我们的掌控之中。

下面对代码进行一点小修改:

  1. int main()
  2. {
  3. int a=10;
  4. int& b=a;
  5. a=30;
  6. b=20;
  7. }

经过对比,可以看到,仅仅是将指针换成了引用,嗯,从语义上看,其行为貌似发现了一些变化,但是在内部发生了什么呢?您请往下走:

  1. subl $16, %esp
  2. call ___main
  3. movl $10, 8(%esp)
  4. leal 8(%esp), %eax
  5. movl %eax, 12(%esp)
  6. movl $30, 8(%esp)
  7. movl 12(%esp), %eax
  8. movl $20, (%eax)

なに!代码发生了什么变化?您看出变化来了吗?如果您看出来了,出门儿右拐大药房滴眼液来两滴。

可以看到汇编层面上,其行为没有任何变化,与指针是一模一样的,咱们就此打住,不用多想,指针要占用4字节的空间,您引用既然和指针是同样的东西,凭什么不占?嗯,其实就这么点事儿。

C++中的引用到底是什么的更多相关文章

  1. 非常易于理解‘类'与'对象’ 间 属性 引用关系,暨《Python 中的引用和类属性的初步理解》读后感

    关键字:名称,名称空间,引用,指针,指针类型的指针(即指向指针的指针) 我读完后的理解总结: 1. 我们知道,python中的变量的赋值操作,变量其实就是一个名称name,赋值就是将name引用到一个 ...

  2. 【Java面试题】15 String s="Hello"; s=s+“world!”;这两行代码执行后,原始的String对象中的内容到底变了没有?String与StringBuffer的超详细讲解!!!!!

    1.Java中哪些类是不能被继承的? 不能被继承的是那些用final关键字修饰的类.一般比较基本的类型或防止扩展类无意间破坏原来方法的实现的类型都应该是final的,在java中,System,Str ...

  3. linux中的selinux到底是什么

    一文彻底明白linux中的selinux到底是什么 2018年06月29日 14:17:30 yanjun821126 阅读数 58877 标签: SElinux 更多 个人分类: Linux   一 ...

  4. Java中的String到底占用多大的内存空间?你所了解的可能都是错误的!!

    写在前面 最近小伙伴加群时,我总是问一个问题:Java中的String类占用多大的内存空间?很多小伙伴的回答着实让我哭笑不得,有说不占空间的,有说1个字节的,有说2个字节的,有说3个字节的,有说不知道 ...

  5. Java中的线程到底有哪些安全策略

    摘要:Java中的线程到底有哪些安全策略呢?本文就为你彻底分析下! 本文分享自华为云社区<[高并发]线程安全策略>,作者:冰 河 . 一.不可变对象 不可变对象需要满足的条件 (1)对象创 ...

  6. php中关于引用(&)详解

    php中关于引用(&)详解 php的引用(就是在变量或者函数.对象等前面加上&符号) 在PHP 中引用的意思是:不同的变量名访问同一个变量内容. 与C语言中的指针是有差别的.C语言中的 ...

  7. 浅谈Java中的引用

    在Java语言中,引用是指,某一个数据,代表的是另外一块内存的的起始地址,那么我们就称这个数据为引用. 在JVM中,GC回收的大致准则,是认定如果不能从根节点,根据引用的不断传递,最终指向到一块内存区 ...

  8. error LNK2019: 无法解析的外部符号 _WinMain@16,该符号在函数 ___tmainCRTStartup 中被引用

    MSVCRTD.lib(crtexew.obj) : error LNK2019: 无法解析的外部符号 _WinMain@16,该符号在函数 ___tmainCRTStartup 中被引用 Debug ...

  9. c++中的引用与指针的区别

    http://blog.csdn.net/lyd_253261362/article/details/4323691 c++中的引用与指针的区别 ★ 相同点: 1. 都是地址的概念: 指针指向一块内存 ...

随机推荐

  1. PL/SQL块loop..各种循环练习

    --利用loop输出1到100的值并求和 ---loop exit end loop set serveroutput on; declare v_i ; v_sum ; begin loop )th ...

  2. 搜索+剪枝——运筹帷幄 (road.cpp)

    运筹帷幄 (road.cpp) [题目描述] 刘邦军行至迷糊林,见其中瘴气围绕,又有青狼猛虎之兽,难于前行. 已知迷糊林是一个共有n个结点的图,点与点之间共有m条道路相连接,每条路有参数t,c,分别表 ...

  3. 解析Tensorflow官方English-Franch翻译器demo

    今天我们来解析下Tensorflow的Seq2Seq的demo.继上篇博客的PTM模型之后,Tensorflow官方也开放了名为translate的demo,这个demo对比之前的PTM要大了很多(首 ...

  4. Linux01--文件管理,常用命令 权限管理

    一.Ø文件系统 1.Linux文件系统特点  • Linux文件系统为单根的树状结构  •文件系统根为”/”  •文件名大小写敏感,除了”/”都是可用字符文件名以”.”开始的为隐藏文件  •文件路径使 ...

  5. jQuery验证控件(转载)

    转自:http://www.cnblogs.com/hejunrex/archive/2011/11/17/2252193.html 官网地址:http://bassistance.de/jquery ...

  6. mysql 插入前 锁表问题

    $dbh = DBI->connect("dbi:mysql:database=$db_name;host=$ip;port=3306",$user,$passwd,{ Ra ...

  7. c++策略模式

    这几天需要学习一下设计模式来为设计代码结构使得代码可扩展性强,代码更加易于维护,不用想很长时间也不知道怎么去设计一个工具的代码. 我的理解策略模式: 1.有一个策略基类,策略类是什么呢?策略类就是一个 ...

  8. const和define的区别

    1.在使用const定义常量时,只能使用标量初始化; 但我们可以使用任何表达式初始化define定义的常量 2.我们可以在条件表达式中使用define定义常量,但绝对不能使用const eg: def ...

  9. EasyList China国内镜像

    镜像地址: http://www.ikay.me/list/easylistchina.txt 与官方服务器每15分钟同步一次 本文固定链接: http://www.ikay.me/easylistc ...

  10. 执行SQL查询脚本

    static void Main(string[] args) { Console.WriteLine("输入用户编号:"); string cusernum = Console. ...