【C++】指针与引用的区别

本文探讨C++中的引用概念,强调引用是对象的别名,而非指针。引用在语言层面表现为对象本身,在底层通常通过指针实现。引用在编译阶段绑定对象后不可改变,而指针可以改变所指对象。引用不涉及野指针问题,且对引用的操作直接作用于被引用对象。
摘要由CSDN通过智能技术生成

对C++中引用概念的一些思考。

如何理解引用与指针的关系

语言语义

引用不是指针(与指针无关),而是对象本身(的别名),对引用的任何操作都是对被引用变量的操作。

底层实现

引用内部通常通过指针实现。


以下分别从语言级别和底层实现进行分析:

C++标准关于引用的说明(语言、语义)

  • 原文

    https://isocpp.org/wiki/faq/references

    Even though a reference is often implemented using an address in the underlying assembly language, please do not think of a reference as a funny looking pointer to an object. A reference is the object, just with another name. It is neither a pointer to the object, nor a copy of the object. It is the object. There is no C++ syntax that lets you operate on the reference itself separate from the object to which it refers.

  • 翻译

    即使经常使用底层汇编语言中的地址来实现引用,也请不要将引用视为指向对象的有趣指针。引用是对象,只是带有另一个名称。它既不是指向该对象的指针,也不是该对象的副本,它是对象。没有C ++语法可让您对引用本身和引用对象进行单独操作。

注:语言标准不需要任何特定的机制,只要行为符合,每个实现都可以自由地以任何方式执行。

引用的原理(实现)

C++源程序

//定义变量
double a = 20.0;
//定义引用
double& b = a;
//定义指针
double* c = &a;

汇编角度:计算机访问内存中的数据,全部通过地址访问。所谓的变量a是对地址的标记,

在代码生成目标文件时,使用地址代替了所有的a,因此目标文件中不存在变量名a(变量a不占用内存)。

VS反汇编

	//定义变量
	double a = 20.0;
/*
013E18D2  movsd       xmm0,mmword ptr [__real@4024000000000000 (013E7BD0h)]  
013E18DA  movsd       mmword ptr [a],xmm0  
*/
	//定义引用
	double& b = a;
/*
013E18DF  lea         eax,[a]  
013E18E2  mov         dword ptr [b],eax  
*/
	//定义指针
	double* c = &a;
/*
013E18E5  lea         eax,[a]  
013E18E8  mov         dword ptr [c],eax  
*/

分析汇编代码

  • 定义变量

    	double a = 20.0;
    /*
    013E18D2  movsd       xmm0,mmword ptr [__real@4024000000000000 (013E7BD0h)]  
    013E18DA  movsd       mmword ptr [a],xmm0
    */  
    
    1. 将双精度浮点数20.0存放在寄存器xmm0中。

    2. 将xmm0的数据存放在以a为地址的内存单元(8字节,64位)。

  • 定义引用

    	double& b = a;
    /*
    013E18DF  lea         eax,[a]  
    013E18E2  mov         dword ptr [b],eax
    */  
    
    1. 将a的地址赋值给寄存器eax。

    2. 将eax中的数据存放在以b为地址的内存单元(双字型,4字节,32位)。

  • 定义指针

    	double* c = &a;
    /*
    013E18E5  lea         eax,[a]  
    013E18E8  mov         dword ptr [c],eax
    */ 
    
    1. 将a的地址赋值给寄存器eax。

    2. 将eax中的数据存放在以c为地址的内存单元(双字型,4字节,32位)。

结论

  1. 如上,引用与指针的汇编代码相同,这说明在VC中引用内部通过指针实现(自身是常量的指针),并且引用只存在于编译阶段。
  2. 引用占用的内存空间为4个字节(见 dword ptr [b],eax),也可定义含有引用类型的成员的类来验证。

一些补充

编译器对于 引用b的解释将自动转换为 *b,故所有对 引用b的操作都是对 变量a的操作。

例如:&b 被编译器解释为 &(*b) ,即&b == &a。


附:指针与引用的区别

指针引用
内存实体,必须分配内存(4字节)变量别名,(内存分配见底层实现)
初始化定义时可不初始化,指向可变定义时必须初始化,绑定实体对象(不可变),不能为NULL
多级一级指针/多级指针一级引用
自增指向下一个空间引用的变量(对象)+1
sizeof指针本身的大小指向变量(对象)的大小
访问方式间接访问直接访问
作为参数传递指针的地址传递变量(对象)的地址
底层实现通过指针

注:指针使用前应做类型检查,避免野指针。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值