一、引用和指针的区别?

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 ;
}

正确的写法二:用引用

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

原文地址:http://www.cnblogs.com/algorithm-code/p/16784368.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性