精华内容
下载资源
问答
  • 什么是指针pointer,什么是引用reference?它们的区别是什么?有什么共性吗?补充:什么时候使用pointer比较好,什么时候用reference?...那么引用的本质是什么,它与指针有什么关系呢?1.引用的底层实现方式引用被...
    c7aff393e1793ca4e2dbc1ff8c9be8e6.png

    什么是指针pointer,什么是引用reference?它们的区别是什么?有什么共性吗?补充:什么时候使用pointer比较好,什么时候用reference? 用pointer和不用有什么区别影响吗?

    引用是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送入变量iint &ri=i;00A013E5  lea        eax,[i]       //将变量i的地址送入寄存器eax00A013E8  mov        dword ptr [ri],eax  //将寄存器的内容(也就是变量i的地址)送入变量riri=8;00A013EB  mov        eax,dword ptr [ri]  //将变量ri的值送入寄存器eax00A013EE  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 指针”得到的是指针本身(所指向的变量或对象的地址)的大小;

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

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

    展开全文
  • 2.1本质:引用是别名,指针是地址2.2具体:2.2.1 从现象上看:指针在运行时可以改变所指向值,而引用一旦与某个对象绑定后就不再改变。意思是:指针可以被重新赋值以指向另一个对象,但是引用则总是在初始化时被...

    2.1本质:引用是别名,指针是地址

    2.2具体:

    2.2.1 从现象上看:

    指针在运行时可以改变所指向的值,而引用一旦与某个对象绑定后就不再改变。意思是:指针可以被重新赋值以指向另一个对象,但是引用则总是在初始化时被指定的对象,以后不能改变,但是指向的内容可以改变。(下面是这个规则的理解)

    string str1 = "a";string str3 = "b";string &str2 = str1;str2 = str3;

    我们看到了“str2 = str3”之后,str2指向的还是str1的地址,str2映射的地址没有发生改变,只是指向的内容发生了改变。 如果用&str2作为左值,编译器会报错,提示“表达式必须是可以修改的值”,这也就是而引用一旦与某个对象绑定后就不再改变的意思,也就是str2是str1的别名,已经映射了str1的地址了,它不能再映射其他的地址,他不能作为其他变量的别名了。

    2.2.2内存分配:

    程序为指针变量分配区域,而不为引用分配内存区域。因为引用生命时必须初始化,从而指向一个已经存在的对象,引用不能为空值。

    2.2.3编译:

    程序在编译时分别将指针和引用添加到符号表上,符号表上记录的是变量名及变量所对应地址。指针变量在符号表上对应的地址值为指针变量的地址值,而引用在符号表上对应的地址值为引用对象的地址值。符号表生成后就不会再改,因此指针可以改变指向的对象(指针变量中的值可以改),而引用对象不能改。这是使用指针不安全而使用引用安全的主要原因。从某种意义上来说引用可以被认为是不能改变的指针。

    2.2.4级数:

    从理论上来说,对于指针没有级数限制,但是引用只有一级。

    int** p1; // 合法。指向指针的指针int*& p2; // 合法。指向指针的引用int&* p3; // 非法。指向引用的指针是非法的int&& p4; // 非法。指向引用的引用是非法的

    2.2.5在效率上:

    其实两者的效率是一致的,因为在底层中,指针和引用的参数都指向同一个地址。在高级编程语言中,因为用*传参可能会指向空的地址或者错误的地址,所以要时时判断参数是否为空,导致降低效率。而用&传参数,则参数不可能为空或者错误地址,这也算稍微提升了一些效率。

    da202959bd53cd80e0c9c754e50a9d75.png
    展开全文
  • 指针引用是C++中两个很重要概念,它们功能看过去很相似,就是是间接引用某个对象,那么我们应该在什么时候使用指针什么时候使用引用呢,下面请允许我慢慢道来:1.永远不要使用一个指向空值的引用。一个引用...

    指针与引用是C++中两个很重要的概念,它们功能看过去很相似,就是都是间接引用某个对象,那么我们应该在什么时候使用指针,什么时候使用引用呢,下面请允许我慢慢道来:

    2a22403e5a44a792c506759919710fda.png

    1.永远不要使用一个指向空值的引用。一个引用必须始终指向某个对象,所以当你确定使用一个变量指向某个对象时,但是这个对象在某些时间可能指向控制,这时候你就必须把变量声明为指针类型,而不是引用!当你确定这个变量始终指向某个对象,这时候你就可以把变量声明为引用类型。

    char *str=0;  //设置指针为空值char &s=*str; //让引用指向空值

    你应该避免出现上面的错误!

    2.因为引用肯定要指向一个对象,所以,在C语言里引用必须被初始化。 string& rs; // 错 误 引 用 必 须 被 初 始 化 string s("xyzzy"); string& rs = s; // 正 确 rs 指 向 s

    指 针 没 有 这 样 的 限 制:

     string *ps; // 未 初 始 化 的 指 针                  // 合 法 但 危 险复制代码

    3.不 存 在 指 向 空 值 的 引 用 这 个 事 实 意 味 着 使 用 引 用 的 代 码 效 率 比 使 用 指 针 的 要 高,因 为 在 使 用 引 用 之 前 不 需 要 测 试 它 的 合 法 性。

    void printDouble(const double& rd){     cout << rd;    // 不 需 要 测 试 rd,它}                   // 肯 定 指 向 一 个 double 值

    相 反 指 针 则 应 该 总 是 被 测 试 防 止 其 为 空:

     void printDouble(const double *pd)    {        if (pd) {    // 检 查 是 否 为 NULL            cout << *pd;        }    }

    4.指 针 与 引 用 的 另 一 个 重 要 的 不 同 是 指 针 可 以 被 重 新 赋 值 以 指 向 另 一 个 不 同 的 对象, 但 是 引 用 则 总 是 指 向 在 初 始 化 时 被 指 定 的 对 象 以 后 不 能 改 变。

    string s1("Nancy");    string s2("Clancy");    string& rs = s1; // rs 引 用 s1    string *ps = &s1; // ps 指 向 s1    rs = s2; // rs 仍 旧 引 用 s1,            // 但 是 s1 的 值 现 在 是           // "Clancy"    ps = &s2; // ps 现 在 指 向 s2;              // s1 没 有 改 变

    5.重 载 某 个 操 作 符 时 你 应 该 使 用 引 用。 最 普 通 的 例 子 是重载操 作 符 []。 这 个 操 作 符 典 型 的 用 法 是 返 回 一 个 目 标 对 象 其 能 被 赋 值。

    总 的 来 说 在 以 下 情 况 下 你 应 该 使 用 指 针 :

    一 是 你 考 虑 到 存 在 不 指 向 任 何 对 象 的可 能, 在 这 种 情 况 下 你 能 够 设 置 指 针 为 空 ;

    二是你 需 要 能 够 在 不 同 的 时 刻 指向 不 同 的 对 象 ,在 这 种 情 况 下 你 能 改 变 指 针 的 指 向。


    如 果 总 是 指 向 一 个 对 象,并 且 一 旦 指 向 一 个 对 象 后 就 不 会 改 变 指 向, 那 么 你 应 该 使 用 引 用。

    获取更多点击下方链接 “了解更多”

    展开全文
  • ……显然,我们能通过名字使用对象。然而在 C++ 中,大多数对象身份”;也就是说对象位于内存某个地址中,如果我们知道...在学习 C 与 C++ 语言时,指针引用类型(C++)总是同学们最头疼知识点之二。...
    ……显然,我们能通过名字使用对象。然而在 C++ 中,大多数对象都“有身份”;也就是说对象位于内存的某个地址中,如果我们知道对象的地址和类型,就能访问它……翻译自 Bjarne Stroustrup 《The C++ Programming Language》(Fourth Edition),Chapter 7.

    在学习 C 与 C++ 语言时,指针与引用类型(C++)总是同学们最头疼的知识点之二。事实上,很多学习过包含指针和/或引用概念程序设计语言的同学也仍然对于为什么会存在这些语言元素的原因缺乏思考。下述代码以 C++ 为例。本文首发于 DGideas 的博客。

    感谢 @szouc 对于数组声明与数组类型隐式转换方面的指正。

    为什么要有指针?

    现代通用电子计算机在程序运行时将所需数据存储于内部存储器(内存)中。通过机器可理解的语言,我们能令电子计算机存取内存中某一指定位置数据,就比如编写一个统计字符串字面量中含有多少个英文小写字母 a 的程序一样,这个程序将用于计数的数据存储于内存空间中的某个位置中。像这样的操作使用是如此频繁,以至于高级程序设计语言专门为程序员提供一种被称为“变量”的语言概念。

    变量(Variable)是一块具名(Named)地址空间。在高级程序设计语言中,我们不再令计算机程序访问某一个特定位置的数据,而只需指出我们需要一块在内存中名为 a 的,存储默认长度整型数据的空间。就像在大多数编程语言中我们的如下定义一样:

    int a;
    

    这样的名称 – 地址一对一的方式使程序员不再关注变量存储的具体位置,这也为兼容于不同内存寻址方式提供了更多方便。然而,并不是所有类型的变量都与计算机为存储该变量所分配的地址空间之间存在一对一的关系,就比如:

    int b[10];
    

    上述 C++ 代码声明了一组连续的,能够存储 10 个默认长度整型变量的空间块,其中标识符(Identifier) b 是数组名称。C++ 标准(conv.array、expr.unary.op 与 expr.sub)指导我们,在某些语境下,包含数组名称 b 的表达式中,标识符 b 可以隐式转换为所分配的空间块中第一块的地址。习惯上,我们使用类似 *b 的包含间接寻址运算符的表达式计算第一块地址所对应的内容

    我们如何读取其余几块的内容?我们并没有一种方式能够直接访问这些空间的内容,但因为我们知道第一块的地址,(编译器)也知道每块默认长度整型的空间有多长,所以编程语言能够提供类似 *(b+2) 或者 b[2] 的方式,允许我们使用首块地址+偏移量(Offset)的方式间接地访问其他块的内容。

    这种通过地址+偏移量间接地访问其他块内容的方式,被称为间接寻址(Indirection)与数组下标(Subscript)运算。像这种保存空间中某一个块的地址的变量,被称为指针。这样,我们很容易接受指针这个概念。

    要注意,由于不同数据类型每块所占用的空间各有不同,所以指针是具有类型的。类型系统有助于指导程序以何种方式去解释内存中某块位置的数据,也能够正确处理类似 *(b+2) 的偏移量操作。

    其他编程语言,比如 Python ,并没有提供指针数据类型。但也通过下标操作(类似 b[2] )提供访问非具名数据的能力。

    那……引用呢?

    想象我们有以下函数,完成一项具有超凡成就的工作:

    void nicejob(int a)
    {
    	a = a * 2;
    }
    

    这段代码意义非凡。它尝试将传入的变量加倍后,将自身改为加倍后的新值。可惜,这段代码不能正常工作。当你尝试执行下列代码时,你就会发现它并不能如期运行:

    #include <iostream>
    
    int main()
    {
    	int x = 2;
    	std::cout << x << std::endl;
    	nicejob(x);
    	std::cout << x << std::endl;
    	return 0;
    }
    
    输出:
    2
    2

    发生了什么?在 nicejob 中对于变量 a 的更改并不会影响 x 的值。包括 C/C++ 在内的多种语言中,当按值传递参数到函数时,函数中获得的变量 a 仅仅是 x 的拷贝——你一直在对拷贝进行操作,当然不会影响到原来的 x 值。

    显然我们有两种方法解决这个问题。我们可以将变量 x地址传递给函数 nicejob ,在函数中修改内存对应位置的 x 值,简单且粗暴。我们还可以指示我们的程序将 x 值本身(而非拷贝!)传入函数 nicejob 中,这样在函数中操作 a 就相当于直接操作 x 一样—— ax 的别名。

    void nicejob(int& a)
    {
    	a = a * 2;
    }
    

    我们只需在函数形式参数列表中将变量 a 的传递类型由 int 改为 int& —— 引用类型即可。这样我们的 nicejob 函数就能如期工作了。

    当我们将一个很大的变量传递给函数时,为了避免在变量拷贝过程中的大量开销(比如,我们传递一个大小为 1GB 的图片给图片处理函数时),我们也使用引用类型。为防止函数对传入变量的误修改,我们可以将函数形参列表(Parameter-list)中的变量类型设为常量引用,就比如 const Image&

    指针提供了一种(直接或间接)访问非具名数据的能力;引用是一种程序变量在构造过程中初始化的方式;DGideas
    展开全文
  • 经常会人问道C++中指针与引用的区别,自己在学习C++过程中也经常会这种困惑。现总结一下。知识点回忆C++中对对象的定义是:指一块能存储数据并且具有某种类型的内存空间。一个对象a,它地址&a,运行...
  • 大蒜是我们日常生活中经常...白皮大蒜红皮大蒜的区别1、红皮大蒜:外皮紫色,蒜头中等大小,种瓣也比较均匀,辣味浓,多早熟,品质较好,适于作蒜薹蒜头栽培,也可作蒜苗栽培。2、白皮大蒜:外皮白色,出蒜薹...
  • 快干防锈油油膜防锈油有什么区别?对于这俩款油品想必大家不陌生,使用防锈油客户都会购买试用过,但是俩者差别具体在哪里,分别适合哪些工件,今天小编就带大家一起去了解!快干防锈油快干防锈油油膜防锈油...
  • 原标题:是普洱茶,生普熟普有什么区别?本文由|九十九度茶文化|原创转载请注明出处说起普洱茶,相信大家不会陌生但是很多茶友对于普洱茶概念并不清楚,甚至有人喝了很久普洱,也不知道自己究竟喝生普还是...
  • 引用,软引用,弱引用,幻象引用有什么区别?不同的引用类型,主要体现是对象不同可达性(reachable)状态对垃圾收集影响。所谓强引用 (Strong Reference) 就是我们常见普通对象引用,只要还有强引用...
  • (〜 ̄△ ̄)〜每天晚上一篇英语知识普及英语罐头本文是我第121篇英语知识...这么多“说”,七嘴八舌究竟有什么区别怎么用呢?今天罐头菌来说这个困扰了90%英语学习者问题。1.Tell (tell/told/told) 告诉t...
  • 问题先看一段代码:int 上述代码,首先定义了一个整型变量a,并赋值为1,然后打印出变量a地址。程序运行结果如下:普通变量:值:1 址:0x6dfef8众所周知,变量a存放于主存中,当CPU执行到以a为操作数指令...
  • 从表面上看,引用和指针非常相似,它们用来让一个变量提供对另一个变量访问。 (推荐学习:go)由于两者提供了许多相同功能,所以常常不清楚它们各自内部机制有什么不同。在本文中,我将说明指针和引用之间....
  • Java的引用和C++的指针有什么区别 Java的引用和C++的指针都是指向一块内存地址,通过引用或指针来完成对内存数据操作。但是它们在实现、原理、作用等方面却有区别。 (1)类型:引用其值为地址数据元素,Java...
  • 引用和指针的区别

    2018-07-26 19:24:55
    C++为什么引用 在学习C语言时候我们知道指针这么一个东西,相信大...引用是引用了对象一个同义词,就像一个别名,对引用操作和对变量直接操作完全一样,引用和指针在语法上看起来不同,但是底层实...
  • java的引用和c++的指针主要8点区别。本质上,它们两者是想通过一个叫引用或者指针的东西,找到要操作的目标,方便在程序中操作。所不同的是java的方法更安全、方便一些、但失去了c++的灵活,也算是对指针的一种...
  • java的引用和C++的指针有什么区别

    千次阅读 2015-07-10 22:04:21
    大多数的C++程序员转学java的时候,都有这样一个疑问,java的引用就是C++的指针吗。其实不完全对,他们之间既有前四外绿的联系, 也有很大的区别。 java的引用和C++的指针都是指向一块内存址的,通过引用或者指针...
  • 引用指针有什么区别

    万次阅读 多人点赞 2019-06-25 15:41:42
    引用指针有什么区别指针和引用都是地址概念,指针指向一块内存,它内容是所指内存地址;引用是某块内存别名。 程序为指针变量分配内存区域,而不为引用分配内存区域。 指针使用时要在前加 * ,引用...
  • 引用和指针的区别: 指针和引用是地址的概念,指针指向一块内存,它的内容是所指内存的地址;引用是某块内存的别名。 程序为指针变量分配内存区域,而不为引用分配内存区域。 指针使用时要在前加 * ,引...
  • 指针和引用的联系与区别 ★ 相同点: 1. 是地址概念; 指针指向一块内存,它内容是所指内存地址;引用是某块内存别名。 ★ 区别: 1. 指针是一个实体,而引用仅是个别名; 2. 引用使用时无需解引用(*),...
  • 在面试的过程中,不少面试官提了一个问题,C++中引用传递和指针传递的区别?应该不少人联想到了swap函数,只知道既可以用引用来实现,又可以用指针传递来实现,至于二者何区别,还真没有考虑过。通过在网上搜集...
  • Java的引用和C++的指针都是指向一块内存地址,通过引用或指针来完成对内存数据操作,就好像风筝线轴一样,通过线轴总是能够找到风筝,但是它们在实现,原理作用等方面却有区别。 (1)类型:引用其值为地址...
  • 引用和指针-面试题39-指针与句柄有什么区别 1:指针对应着一个数据在内存中地址,得到了指针就可以自由地修改该数据。Windows并不希望一般程序修改其内部数据结构,因为这样太不安全。所以Windows给每个使用...
  • 摘自『高质量c++编程』指针引用,在More Effective C++ 的条款一详细讲述,我给你转过来 条款一:指针引用的区别 指针引用看上去完全不同(指针用操作符’*’’->’,引用使用操作符’.’),但是它们...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 439
精华内容 175
关键字:

引用和指针的区别都有什么