一、引用和指针的区别?
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