首页 > 编程语言 >掌握C++的左值引用和初识右值引用

掌握C++的左值引用和初识右值引用

时间:2022-10-15 22:57:41浏览次数:49  
标签:20 右值 int 引用 左值 地址 内存 指针

一、引用和指针的区别?

1、左值引用和右值引用

2、引用的实例

 

1、引用是更安全的指针

(1)安全性:

引用是必须初始化的,指针可以不初始化。

 引用能够保证一定能够引用到一个内存(因为必须初始化嘛),而指针有可能是野指针,需要通过开发者自己来保证指针的正确性。所以引用比指针更安全些。

(2)指针性

#include<iostream>

using namespace std;

int main() 
{
    int a = 10;
    int *p = &a;    // 指针指向a内存,因为指针有自己单独的内存,所以你需要取a的地址。这里的&叫“取地址运算符”,p是指针类型变量,所以p存a的地址
    int &b = a;     // 引用变量的作用就是起别名,相当于给a这块内存取了个别名b,这块内存叫a也可以,叫b也可以

    *p = 20;
    cout << a << " " << *p << " " << b << endl;     //访问的都是同一块内存

    b = 30;
    cout << a << " " << *p << " " << b << endl;     //访问的都是同一块内存

    return 0;
}
输出结果:
20 20 20 30 30 30

注意:这里修改p的值,不会影响a的值,修改a的值,也不会影响p的值,因为p存的是地址,a存的是数据,两者无关。但是修改*p会影响a的值,或者修改a会影响*p的值,因为p是存a的地址,*p表示取a中的数据,a和*p互相等同,息息相关。

 


在汇编层面上看,没有引用这一说,引用变量在汇编中对应的操作就是跟指针变量一样的。

 当我们为引用变量赋值,b = 30,在汇编层面上,编译器会自动为引用变量做一个解引用的操作(因为本来在汇编层面上,引用变量≈指针变量,b = 30,又没有*,那编译器就得给它加上),所以本质上b = 30并不是给b赋值,而是给b所指向的内存赋值。

 b = 30转成汇编语言的第二句话,是对eax,也就是对a的地址进行了一个解引用的操作(得到a的内存),然后把1Eh(即30)赋给dword ptr [eax](即a的内存)来修改a的内存的值。

int *p = &a转成汇编的第二句话,dword ptr [p]应该是对p进行一个解引用的操作,即得到p这个地址所对应的内存,然后把eax的值(即a的地址)放进去。

综上,引用是更安全的指针。

 

int &c = 20;  这个语句是无法运行成功的,根据上面引用所对应的汇编代码,是需要先取20的地址,然后将其地址放到引用变量c的内存中,但是20是没有地址的呀!!它只是一个立即数(常量),所以这句话是无法运行成功的。

 

2、引用只有一级引用,没有多级引用,指针可以有一级指针,也可以有多级指针

3、定义一个引用变量,和定义一个指针变量,其汇编指令是一模一样的;通过引用变量修改所引用内存的值,和通过指针解引用修改指针指向的内存的值,其底层指令也是一模一样的

 

二、swap函数

1、错误的写法

#include <iostream>

using namespace std;

void swap(int *x, int *y) {
    int *tmp = x;
    x = y;
    y = tmp;
}

int main() {
    int a = 20, b = 5;
    swap(&a, &b);
    cout << "a:"<< a << "  ";
    cout << "b:"<< b ;
}
错误写法
#include <iostream>

using namespace std;

void swap(int *x, int *y) {
    cout << "swap()---start---"<<endl;
    int *tmp = x;
    cout << "*tmp: "<<*tmp << endl;
    x = y;
    cout << "*x: "<< *x <<endl;
    y = tmp;
    cout << "*y: " << *y << endl;
    cout << "swap()---end---" << endl<< endl;
}

int main() {
    int a = 20, b = 5;
    swap(&a, &b);
    cout << "a:"<< a << "  ";
    cout << "b:"<< b ;
}




输出结果:
swap()---start---
*tmp: 20
*x: 5
*y: 20
swap()---end---

a:20  b:5
对错误代码的分析

分析:从输出结果看出来,*x是等于5,并不是意味着*x和*y进行了交换(*表示解引用,*x表示解开x的值,即解开a的地址,取出a内存中的值,所以*x表示x指针所指向的内存的值)!!!!而是说明x和y进行了交换,x和y是两个int *型的指针,指针也有自己的内存,它们存放的分别是a和b的地址,上面的那种写法,只是对指针的内存的内容(a和b的地址)进行交换,而不是对指针所指向的内存进行交换(即未对指针内存中的内容(即地址)所对应的内存的内容(即a和b的值)进行交换)。

此错误的swap函数只对指针的内存进行了交换操作,并未对指针所指向的内存进行交换操作。

 

2、正确的两种写法

#include <iostream>

using namespace std;

void swap(int *x, int *y) {
    int tmp = *x;
    *x = *y;
    *y = tmp;
}

int main() {
    int a = 20, b = 5;
    swap(&a, &b);
    cout << "a:"<< a << "  ";
    cout << "b:"<< b ;
}
正确的写法一:用指针
#include <iostream>

using namespace std;

void swap(int &x, int &y) {     // 汇编层面,引用变量 ≈ 指针变量
    int tmp = x;    // 编译器仍会对x进行一个解引用的操作
    x = y;
    y = tmp;
}

int main() {
    int a = 20, b = 5;
    swap(a, b);     // 传过去仍然是a和b的地址
    cout << "a:"<< a << "  ";
    cout << "b:"<< b ;
}
正确的写法二:用引用

其实从汇编角度上看,写法一和写法二完全一样,只不过引用会保证必有初始值,会更安全些,所以写法二会好一点。

标签:20,右值,int,引用,左值,地址,内存,指针
From: https://www.cnblogs.com/algorithm-code/p/16784368.html

相关文章

  • Java引用传递-初级
    Java引用传递-初级packageoop;//引用传递,对象。本质还是值传递publicclassDemo04{  publicstaticvoidmain(String[]args){    Personperson=new......
  • JavaScript 值类型与引用类型
    JS数据类型JS有两种数据类型分别为值类型,引用类型值类型:Number、String、Boolean、Null、Undefined、Symbol(ES6);引用类型:Object;值类型值类型存放在栈中,可以直接按值......
  • excel表格结构化引用
    结构化引用,听起来很神秘的一个词,但是我们几乎每一套题都实实在在的用到它。不需要会书写结构化引用,只要能读懂即可,甚至不读懂也对做题影响不大,但终究是一种磕绊。情景再现公......
  • Excel “ 结构化 引用 ”
    一、概念列举1.地址引用☆相对引用: A1☆绝对引用: $A$1☆混合引用: A$1或 $A12.名称引用定义名称→引用名称3.结构化引用套用表格格式→结构化引用二、何为“结......
  • 认识 “结构化 引用”
    一、概念列举1.地址引用☆相对引用: A1☆绝对引用: $A$1☆混合引用: A$1或 $A12.名称引用定义名称→引用名称3.结构化引用套用表格格式→结构化引用二、何为“结......
  • 何为 “引用”
    一、概念列举1.地址引用☆相对引用:A1☆绝对引用:$A$1☆混合引用:A$1或 $A12.名称引用定义名称→引用名称3.结构化引用套用表格格式→结构化引用二、何为“引用......
  • 4. HTML引用CSS(4种方法)
    1. 前言CSS样式需要引用到HTML中才能真正有效,那么如何才能在HTML中引用CSS呢?下面就来介绍一下。2.内嵌样式表您可以在HTML头部(<head>标签内)的<style>标签......
  • java 在命令行下引用三方包编译并执行
    参考:https://blog.csdn.net/xuejiaodream/article/details/79161938方法:命令行进行.java当前目录,执行下面的命令编译java程序,$javac-cp".:fastjson-1.2.4.jar"HttpDemo......
  • Python 变量与引用
    一、变量的引用  1、在python中,变量和引用都保存在内存中  2、在python中,函数的传递以及返回值都是靠引用传递的二、引用的概念  1、在python中,变量和数据是分......
  • Unity关于引用.Net或其他C# dll的问题。(我是用的版本是2018.3)
      首先,因为我是用到了.NetWinForm中的中的一个System.Windows.WinForms中的类(OpenFileDialog)就是打开就是选择资源的一个对话框。ALT+Enter可以直接在VS中引用,但是......