精华内容
下载资源
问答
  • 1.引用必须在定义时就要初始化,而指针不需要。 例如: int a=0; int &b=a; int *ptr;...2.引用不占用内存空间,它只是变量的别名而已,而指针是占用内存空间的。在C++中没有取引用地址的说法

    1.引用必须在定义时就要初始化,而指针不需要。

    例如:

    int a=0;
    int &b=a;
    int *ptr;

    2.引用不占用内存空间,它只是变量的别名而已,而指针是占用内存空间的。在C++中没有取引用地址的说法。

     

    展开全文
  • 2. 引用与指针的区别 2.1 2.2 2.3 2.4 引用是C++引入的重要机制(C语言没有引用),它使原来在C中必须用指针来实现的功能有了另一种实现的选择,在书写形式上更为简洁。那么引用的本质是什么,它与指针又有什么...

    目录

    1. 引用的底层实现方式

    1.1 从对象出发对引用和指针的理解

    2. 引用与指针的区别

    2.1

    2.2

    2.3

    2.4


    引用是C++引入的重要机制(C语言没有引用),它使原来在C中必须用指针来实现的功能有了另一种实现的选择,在书写形式上更为简洁。那么引用的本质是什么,它与指针又有什么关系呢?

    1. 引用的底层实现方式

    引用被称为变量的别名,它不能脱离被引用对象独立存在,这是在高级语言层面的概念和理解,并未解释引用的实现方式。常见错误说法是“引用”自身不是一个变量,甚至编译器可以不以引用分配空间。

    实际上,引用本身是一个变量,只不过这个变量的定义和使用与普通变量有显著的不同。为了解引用变量底层实现机制,考查如下代码:

    int i=5;
    int &ri=i;
    ri=8;

    在Visual Studio 2017环境的debug模式调试代码,反汇编查看源码对应的汇编代码的步骤是:调试->窗口->反汇编,即可得到如下原码对应的汇编代码:

    int i=5;
    00A013DE  mov        dword ptr [i],5    	//将文字常量5送入变量i
    int &ri=i;
    00A013E5  lea        eax,[i]  	 	    	//将变量i的地址送入寄存器eax
    00A013E8  mov        dword ptr [ri],eax  	//将寄存器的内容(也就是变量i的地址)送入变量ri
    ri=8;
    00A013EB  mov        eax,dword ptr [ri]  	//将变量ri的值送入寄存器eax
    00A013EE  mov        dword ptr [eax],8   	//将数值8送入以eax的内容为地址的单元中
    return 0;
    00A013F4  xor        eax,eax
    

    考查以上代码,在汇编代码中,ri的数据类型为dword,也就是说,ri要在内存中占据4个字节的位置。所以,ri的确是一个变量,它存放的是被引用对象的地址。由于通常情况下,地址是由指针变量存放的,那么,指针变量和引用变量有什么区别呢?使用指针常量实现上面的代码功能。考查如下代码:

    int i=5;
    int* const pi=&i;
    *pi=8;

    按照相同的方式,在VS2017中得都如下汇编代码:

    int i=5;
    011F13DE  mov         dword ptr [i],5  
    int * const pi=&i;
    011F13E5  lea         eax,[i]  
    011F13E8  mov         dword ptr [pi],eax  
    *pi=8;
    011F13EB  mov         eax,dword ptr [pi]  
    011F13EE  mov         dword ptr [eax],8  
    

    观察以上代码可以看出:

    1. 除了pi与ri变量名不同,所得汇编代码与第一段所对应的汇编代码完全一样。所以,引用变量在功能上等于一个指针常量,即一旦指向某一个单元就不能在指向别处。
    2. 在底层,引用变量由指针按照指针常量的方式实现。

    1.1 从对象出发对引用和指针的理解

    C++primer中对 对象的定义:对象是指一块能存储数据并具有某种类型的内存空间
    一个对象a,它有地址&a,运行程序时,计算机会为该对象分配存储空间,来存储该对象的值,我们通过该对象的地址,来访问存储空间中的值

    指针p也是对象,它同样有地址&p和存储的值p,只不过,p存储的数据类型是数据的地址。如果我们要以p中存储的数据为地址,来访问对象的值,则要在p前加解引用操作符"*",即*p。

    我们可以把引用理解成变量的别名。定义一个引用的时候,程序把该引用和它的初始值绑定在一起,而不是拷贝它。计算机必须在声明r的同时就要对它初始化,并且,r一经声明,就不可以再和其它对象绑定在一起了。

    实际上,你也可以把引用看做是通过一个常量指针来实现的,它只能绑定到初始化它的对象上。

    因此,引用的一个优点是它一定不为空,因此相对于指针,它不用检查它所指对象是否为空,这增加了效率。

    综上,引用只是c++语法糖,可以看作编译器自动完成取地址、解引用的常量指针。引用区别于指针的特性都是编译器约束完成的,一旦编译成汇编就和指针一样。

    2. 引用与指针的区别

    2.1

    引用和指针,在内存中都是占用4个字节(32bits系统中)的存储空间。指针和引用存放的都是被引用对象的地址,都必须在定义的同时进行初始化。

    2.2

    指针常量本身(以p为例)允许寻址,即&p返回指针常量(常变量)本身的地址,被引用对象用*p表示;引用变量本身(以r为例)不允许寻址,&r返回的是被引用对象的地址,而不是变量r的地址(r的地址由编译器掌握,程序员无法直接对它进行存取),被引用对象直接用r表示。

    2.3

    凡是使用了引用变量的代码,都可以转换成使用指针常量的对应形式的代码,只不过书写形式上要繁琐一些。反过来,由于对引用变量使用方式上的限制,使用指针常量能够实现的功能,却不一定能够用引用来实现。

    例如,下面的代码是合法的:

    int i=5,j=6;
    int* const array[]={&i,&j};

    而如下代码是非法的:

    int i=5,j=6;
    int& array[]={i,j};

    也就是说,数组元素允许是指针常量,却不允许是引用。C++语言机制如此规定,原因是避免C++语法变得过于晦涩。假如定义一个“引用的数组”,那么array[0]=8;这条语句该如何理解?是将数组元素array[0]本身的值变成8呢,还是将array[0]所引用的对象的值变成8呢?对于程序员来说,这种解释上的二义性对正确编程是一种严重的威胁,毕竟程序员在编写程序的时候,不可能每次使用数组时都要回过头去检查数组的原始定义。

    即得出两个不同:引用只能在定义时被初始化一次,之后不可变,但是指针可变;引用没有 const,指针有 const。

    • 引用没有顶层const即int& const,因为引用本身就不可变,所以在加顶层const也没有意义; 但是可以有底层const即 const int&,这表示引用所引用的对象本身是常量
    • 指针既有顶层const(int* const 指针本身不可变),也有底层const(const int* 指针所指向的对象不可变)

    2.4

    • 尽量用引用代替指针
    • 引用使用时无需解引用(*),指针需要解引用;
    • “sizeof 引用”得到的是所指向的变量(对象)的大小,而“sizeof 指针”得到的是指针本身(所指向的变量或对象的地址)的大小;
    • 引用不能为空,指针可以为空;
    • 指针和引用的自增(++)运算意义不一样;引用代表所指向的对象对象执行++,指针自增内存地址。
    展开全文
  • Java中没有指针的说法,Java中的引用就类似于C++的指针, Java的引用是栈区的一个变量, 如果引用的是基本数据类型,那它存储着就是栈区的一块内存,(因为普通基本数据类型由栈区管,long、int、short、byte、float...
        

    Java的引用 及 Java函数形参是传值还是引用

    Java中没有指针的说法,Java中的引用就类似于C++的指针,
    Java的引用是栈区的一个变量,
    如果引用的是基本数据类型,那它存储着就是栈区的一块内存,(因为普通基本数据类型由栈区管,long、int、short、byte、float、double、string、boolean),做形参时是传值调用;
    如果引用的是new出来的实例(new String('a')也算,直接写'a'则存在栈区),则这个引用存储的是堆区一块内存的地址(这个时候就类似于C++的指针),做形参时是传引用调用,即C++中的传指针调用;

    C++中——

    传值调用:形参的值跟传来的变量的值没有底层联系,各不相犯;
    传指针调用:形参的值跟传来的变量的值是同一块内存的地址,可以修改同一块内存的东西,但是形参跟传来的变量是两个不同的变量;
    传引用调用:形参只是取别名,是传来的变量的另外一个名字,形参跟传来的变量是同一个变量;【C++中的引用就是另外一个变量的别名,实际上是跟那个变量是同一个变量】

    C++指针与Java引用的区别

    C++的指针存储的是一个变量的地址*指针是这个变量的内容

    int  var = 20;   // 实际变量的声明
    int  *ip;        // 指针变量的声明
    ip = &var;       // 在指针变量中存储 var 的地址
    ---
    Value of var variable: 20
    Address stored in ip variable: 0xbfc601ac
    Value of *ip variable: 20
    

    还有一种情况,
    CTest* pTest = new CTest();
    这个时候指针的内容就是一块堆内存的地址

    • C++指针存储的可以是一个变量的地址或者一块堆内存的地址

      Java中的引用存储了一块栈/堆内存的地址
      但是使用引用的时候得到的是那块内存的内容


      所以本质上讲,
      当它们都是用于存储一块堆内存的地址的时候,
      也就是存储一个通过newnew出来的类实例的时候,
      它们就是一样的,其他情况它们则不一样;

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

    可见这篇文章

    • 指针存储的是一个变量的地址;引用就是另外一个变量的别名,实际上是跟那个变量是同一个变量;
    • 不存在空引用。引用必须连接到一块合法的内存。
    • 一旦引用被初始化为一个对象,就不能被指向到另一个对象。指针可以在任何时候指向到另一个对象。
    • 引用必须在创建时被初始化。指针可以在任何时间被初始化。
       // 声明简单的变量
       int    i;
       double d;
     
       // 声明引用变量
       int&    r = i;
       double& s = d;
    

    C++与Java创建类实例的区别

    C++中类的实例化的两种方法

    Class class;对于C++来说,是在栈中实例化一个类实例,同时也调用了Class类的默认或者无参数的构造函数!!
    对于Java来说则只是一个类实例的引用的声明,
    还没有初始化、实例化,跟别说调用构造函数了;

    Class class = new Class();只能是Java的写法,
    它跟C++中的 Class* class = new Class();是相类似的过程,
    都是在堆区开辟一块内存,初始化实例化好这块内存后,把它的地址赋值给class;

    也就是C++的类实例可以选择性放在栈、堆中;
    Java的类实例只能放在堆中;
    而C++使用new的时候需要使用指针,
    Java直接用引用,没有指针;

    展开全文
  • 那么引用的本质是什么,它与指针又有什么关系呢? 1.引用的底层实现方式 引用被称为变量别名,它不能脱离被引用对象独立存在,这是在高级语言层面概念和理解,并未解释引用的实现方式。常见错误说法是“引用”...

    转自:https://www.zhihu.com/question/37608201/answer/545635054
     

    引用是C++引入的重要机制(C语言没有引用),它使原来在C中必须用指针来实现的功能有了另一种实现的选择,在书写形式上更为简洁。那么引用的本质是什么,它与指针又有什么关系呢?

    1.引用的底层实现方式

    引用被称为变量的别名,它不能脱离被引用对象独立存在,这是在高级语言层面的概念和理解,并未解释引用的实现方式。常见错误说法是“引用”自身不是一个变量,甚至编译器可以不以引用分配空间。

    实际上,引用本身是一个变量,只不过这个变量的定义和使用与普通变量有显著的不同。为了解引用变量底层实现机制,考查如下代码:

    int i=5;
    int &ri=i;
    ri=8;

    在Visual Studio 2017环境的debug模式调试代码,反汇编查看源码对应的汇编代码的步骤是:调试->窗口->反汇编,即可得到如下原码对应的汇编代码:

    int i=5;
    00A013DE  mov        dword ptr [i],5    	//将文字常量5送入变量i
    int &ri=i;
    00A013E5  lea        eax,[i]  	 	    	//将变量i的地址送入寄存器eax
    00A013E8  mov        dword ptr [ri],eax  	//将寄存器的内容(也就是变量i的地址)送入变量ri
    ri=8;
    00A013EB  mov        eax,dword ptr [ri]  	//将变量ri的值送入寄存器eax
    00A013EE  mov        dword ptr [eax],8   	//将数值8送入以eax的内容为地址的单元中
    return 0;
    00A013F4  xor        eax,eax
    

    考查以上代码,在汇编代码中,ri的数据类型为dword,也就是说,ri要在内存中占据4个字节的位置。所以,ri的确是一个变量,它存放的是被引用对象的地址。由于通常情况下,地址是由指针变量存放的,那么,指针变量和引用变量有什么区别呢?使用指针常量实现上面的代码功能。考查如下代码:

    int i=5;
    int* const pi=&i;
    *pi=8;

    按照相同的方式,在VS2017中得都如下汇编代码:

    int i=5;
    011F13DE  mov         dword ptr [i],5  
    int * const pi=&i;
    011F13E5  lea         eax,[i]  
    011F13E8  mov         dword ptr [pi],eax  
    *pi=8;
    011F13EB  mov         eax,dword ptr [pi]  
    011F13EE  mov         dword ptr [eax],8  
    

    观察以上代码可以看出:

    (1)除了pi与ri变量名不同,所得汇编代码与第一段所对应的汇编代码完全一样。所以,引用变量在功能上等于一个指针常量,即一旦指向某一个单元就不能在指向别处。

    (2)在底层,引用变量由指针按照指针常量的方式实现。

    2.高级语言层面引用与指针常量的关系

    1.引用和指针,在内存中都是占用4个字节(32bits系统中)的存储空间。指针和引用存放的都是被引用对象的地址,都必须在定义的同时进行初始化。

    2.指针常量本身(以p为例)允许寻址,即&p返回指针常量(常变量)本身的地址,被引用对象用*p表示;引用变量本身(以r为例)不允许寻址,&r返回的是被引用对象的地址,而不是变量r的地址(r的地址由编译器掌握,程序员无法直接对它进行存取),被引用对象直接用r表示。

    3.凡是使用了引用变量的代码,都可以转换成使用指针常量的对应形式的代码,只不过书写形式上要繁琐一些。反过来,由于对引用变量使用方式上的限制,使用指针常量能够实现的功能,却不一定能够用引用来实现。

    例如,下面的代码是合法的:

    int i=5,j=6;
    int* const array[]={&i,&j};

    而如下代码是非法的:

    int i=5,j=6;
    int& array[]={i,j};

    也就是说,数组元素允许是指针常量,却不允许是引用。C++语言机制如此规定,原因是避免C++语法变得过于晦涩。假如定义一个“引用的数组”,那么array[0]=8;这条语句该如何理解?是将数组元素array[0]本身的值变成8呢,还是将array[0]所引用的对象的值变成8呢?对于程序员来说,这种解释上的二义性对正确编程是一种严重的威胁,毕竟程序员在编写程序的时候,不可能每次使用数组时都要回过头去检查数组的原始定义。

    即得出两个不同:引用只能在定义时被初始化一次,之后不可变,但是指针可变;引用没有 const,指针有 const。

    4.一些其他不同:

    引用使用时无需解引用(*),指针需要解引用;

    “sizeof 引用”得到的是所指向的变量(对象)的大小,而“sizeof 指针”得到的是指针本身(所指向的变量或对象的地址)的大小;

    引用不能为空,指针可以为空;

    指针和引用的自增(++)运算意义不一样;引用自增被引用对象的值,指针自增内存地址。

    展开全文
  • 用参数传递来 辨析 指针与引用的区别 在谭浩强错误的c程序设计中的最大错误就是: 传参有两种方式,传址和传值!!!!, 这句话我想说: 完全错,大错特错,错上加错,误人子弟。 指针也是一个变量,指针也值的 ...
  • 那么引用的本质是什么,它与指针又有什么关系呢? 二、引用的实现方式 引用被称为变量别名,它不能脱离被引用对象独立存在,这是在高级语言层面概念和理解,并未解释引用的实现方式。常见错误说法是“引用”...
  • 指针与引用的区别: 1.指针可以为空指针,而引用不能为空,没有空引用的说法; 2.针对上一条区别,指针初始化时可为空指针,而引用初始化必须指定代表对象; 3.指针在使用过程中可以变化其指向的对象(指针常量...
  • C++关于指针,引用,函数和const的关系C++知识梳理指针与引用的区别指针和引用的在临时数据上的限制Const和引用结合使用时const 引用与类型转换引用类型的函数形参请尽可能的使用 const C++知识梳理 指针与引用...
  • 值类型和引用类型的区别: 似乎“值类型和引用类型的区别”是今年面试的流行趋势,我已然是连续三次(目前总共也就三次)面试第一个问题就遇到这个了,这是多大的概率啊,100%. 言归正传,咱还是先来探讨探讨这二者...
  • 1.4 再看指针数组1.5 数组的指针之赋值1.6 进一步观察行指针,即数组的指针的移动2 对于数组的地址2.1 概念3 二维数组的解引用4 解引用和下标4.1 下标是数组说法,解引用是指针说法4.2 为了方便理解,再一次详细描述...
  • 引用也是一种数据类型,我们可以把它想象为类似 C 语言中指针的东西,它指示了对象在内存中的地址——只不过我们不能够观察到这个地址究竟是什么。  如果我们定义了不止一个引用指向同一个对象,那么这些引用是不...
  • 1. 在C++中,引用指针的区别是() A. 引用总是指向一个对象,指针可能不指向对象 B. 引用和指针都可以被重新赋值 C. 引用不能用const修饰,而指针可以 D. 引用创建时必须初始化,而指针则可以在任何时候被初始化 ...
  • C++(卡某柯复盘一下)

    2020-09-06 09:25:29
    1.前置操作符和后置操作符区别?...4.关于指针引用的区别 5.c++模板实例化发生在程序编译时候 6.一个c++类默认函数有.,且为public属性? 7.Int(*func)(int*p,int(*f)(int*)));是否正确 8.填空题 ...
  • 面试题12:数组名和指针的区别 5.4 函数指针 面试题13:请解析(*(void (*)())0)()的含义 面试题14:指出程序的错误 5.5 “野指针” 面试题15:如何避免“野指针” 面试题16:程序是否正确 面试题17:指出程序的错误 ...
  • 编程新手真言......

    2009-04-02 20:25:15
    8.28 可复用可移殖的区别 190 8.28 再谈可复用 193 8.29 真正的可复用 193 8.30 你能理解XP编程吗 194 8.31 构件接口,软工 195 8.32 设计方法论 196 8.33 真正的interface 198 8.34 真正的对接口进行编程 200 ...
  • 3.1.1 C++中引用与指针的区别 3.1.2 C/C++程序的内存分区 3.1.3 快速排序的思想、时间复杂度、实现以及优化方法 3.1.4 IO模型——IO多路复用机制? 3.1.5 常用的Linux命令 3.1.6 C中变量的存储类型有哪些? ...
  • windows 程序设计

    2011-07-24 21:16:30
    虽然有一些争议,但现在已非常清楚,GUI是(Microsoft的Charles Simonyi的说法)一个在个人计算机工业史上集各方面技术大成于一体的最重要产物。 所有GUI都在点矩阵对应的视讯显示器上处理图形。图形提供了使用屏幕...
  • flash shiti

    2014-03-14 10:32:41
    11. 全等(===)运算符和相同运算符基本相似,但是它们有一个很重要的区别 □ A. 全等(===)运算符执行数据类型的转换 □ B. 全等(===)运算符不执行数据类型的转换 □ C. 全等(===)运算符永远返回...
  • php高级开发教程说明

    2008-11-27 11:39:22
    编码和差编码之间究竟有何区别呢?实际上,这个问题很简单。好代码(确实好 代码)能够像一本书一样被阅读。你能从任何地方读起,并且能够时刻意识到你所读这些 行是干什么用,它们在什么条件下执行,...

空空如也

空空如也

1
收藏数 20
精华内容 8
关键字:

引用与指针的区别的说法