栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++ 引用和指针的区别

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++ 引用和指针的区别

众所周知,引用是某一个变量的别称。指针是一个变量,变量的内容是某一个变量的地址

下面从实现方式和应用两个维度剖析这两者的不同

指针的实现

指针从本质上来讲还是一个变量。和普通变量不一样的是:指针变量中存放的是其他变量的地址(变量都是需要占用存储空间的,有一个对应的地址)。

引用的实现

之前自己理解的引用不是变量。是在编译期间被编译器替换掉的一个符号,相当于是一个宏。这个理解是错误的。引用是一个变量,实现上可以把他当成一个不能改变其内容的指针。看下面代码的反汇编

源码:

#include 
#include 

void func(int& a) {
    a = 1;
    printf("func a address:%pn", &a);
    return;
}

int main(int argc, char* argv[]) {
    int mainA = 2;
    printf("main mainA address:%pn", &mainA);
    func(mainA);
    int & A = mainA;
    A = 3;
    printf("main A address:%pn",&A);
    return 0;
}

函数func对应的汇编代码

0804841d <_Z4funcRi>:
 804841d:       55                      push   %ebp
 804841e:       89 e5                   mov    %esp,%ebp
 8048420:       83 ec 18                sub    $0x18,%esp
 8048423:       8b 45 08                mov    0x8(%ebp),%eax
 8048426:       c7 00 01 00 00 00       movl   $0x1,(%eax)
 804842c:       8b 45 08                mov    0x8(%ebp),%eax
 804842f:       89 44 24 04             mov    %eax,0x4(%esp)
 8048433:       c7 04 24 30 85 04 08    movl   $0x8048530,(%esp)
 804843a:       e8 b1 fe ff ff          call   80482f0 
 804843f:       90                      nop
 8048440:       c9                      leave  
 8048441:       c3                      ret    

指令8048423处是把入栈的参数放到寄存器eax中。指令8048426处是把数字1放入eax所指示的地址上。那么我们需要搞清楚在调用函数func的时候入栈的参数是什么?

看下main函数的汇编代码

08048442 
: 8048442: 55 push %ebp 8048443: 89 e5 mov %esp,%ebp 8048445: 83 e4 f0 and $0xfffffff0,%esp 8048448: 83 ec 20 sub $0x20,%esp 804844b: c7 44 24 18 02 00 00 movl $0x2,0x18(%esp) 8048452: 00 8048453: 8d 44 24 18 lea 0x18(%esp),%eax 8048457: 89 44 24 04 mov %eax,0x4(%esp) 804845b: c7 04 24 43 85 04 08 movl $0x8048543,(%esp) 8048462: e8 89 fe ff ff call 80482f0 8048467: 8d 44 24 18 lea 0x18(%esp),%eax 804846b: 89 04 24 mov %eax,(%esp) 804846e: e8 aa ff ff ff call 804841d <_Z4funcRi> 8048473: 8d 44 24 18 lea 0x18(%esp),%eax 8048477: 89 44 24 1c mov %eax,0x1c(%esp) 804847b: 8b 44 24 1c mov 0x1c(%esp),%eax 804847f: c7 00 03 00 00 00 movl $0x3,(%eax) 8048485: 8b 44 24 1c mov 0x1c(%esp),%eax 8048489: 89 44 24 04 mov %eax,0x4(%esp) 804848d: c7 04 24 5a 85 04 08 movl $0x804855a,(%esp) 8048494: e8 57 fe ff ff call 80482f0 8048499: b8 00 00 00 00 mov $0x0,%eax 804849e: c9 leave 804849f: c3 ret

指令804844b处,把数字2赋值给变量mainA。指令8048467及后面的两条指令是对函数func的调用。分析这三条指令

指令8048467: 把esp+0x18 (变量mainA的地址)赋值给寄存器eax。

指令804846b: 把eax的值入栈。

指令804846e: 调用函数func。

可以得出结论:调用函数func时,入栈的参数是变量mainA的地址。函数调用过程的引用变量传递的是变量的地址。那么还有另外一个问题:在非函数调用的场景下,引用变量是怎么实现的呢

分析main函数中的引用变量A是怎么实现的,有关的指令为8048473及其后的三条指令

指令8048473:把esp+0x18(变量mainA的地址)赋值给寄存器eax

指令8048477:把eax的值放到esp+0x1c(变量A的地址)指示的地址空间中

指令804847b:把esp+0x1c(变量A的地址)地址空间中的内容(变量mainA的地址)赋值给寄存器eax,

指令804847f:把数字3放到eax指示的地址空间中

可以得出结论:在非函数调用的场景下,引用变量也是通过指针实现的。

编译器在处理引用变量的特殊处理:(待验证)

1. 对于引用变量 取地址符& 获取的是引用变量的内容,而并非是引用变量的地址

2. 对于引用变量的赋值,把需要赋值的内容放到引用变量的内容所指示的地址空间中

那么对于多级引用的情况是什么样子的呢?todo

1. int a =2; int & b = a; int & c = b;

引用的使用

可以把引用的使用当成一个不能改变其内容的指针变量。而普通的指针变量是可以改变变量中的内容的

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/857462.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号