指针与引用的一些见解与验证

来源:互联网 发布:c语言杨辉三角流程图 编辑:程序博客网 时间:2024/06/07 06:50

昨晚讨论到了指针与引用的区别,小M同学说:指针与引用是一样的都是用指针实现的。我问:既然都是指针,那为什么还有引用出现?小M说:引用方便,便于理解!我问:引用一定方便吗?小M说:反正都是用指针实现的!我说:怎么实现的我不知道,同样我也不否认:指针与引用都是地址的概念,但是都是用指针实现的话,那么你解释下:

  1. 指针定义之后可以NULL,而引用定义之后必须马上初始化,不能为空;
  2. 指针可以随时改变其值,而引用在初始化之后就不能改变其对象(值);
  3. sizeof 指针 得到的是指针变量的大小,而sizeof 引用 得到的是引用对象的大小;
  4. 指针与引用的自增(减)运算意义也不一样;
  5. 就定义来说,指针指向的是一块内存,他的内容为其所指向内存的地址,引用是某一块内存的别名;

很明显,以上5点的区别说明了二者之间是有不同的。但是即便是清楚二者之间的区别,我们在使用的时候还是不清楚怎么使用,下面是我整理的一些二者的用法:

概念上    

指针,其实,指针本质上是存放的变量地址的一个变量,在逻辑上是可以独立的,既然是独立的,那么其所指向的地址,以及其指向的地址中存放的数据都是可以改变的。

引用,是变量的一个别名,既然是别名,那么他是依附于变量存在的,即其具有依附性,这也解释了为什么引用在一开始就必须被初始化,其引用的对象在其整个生命周期是不能被改变的 ( 对某一变量的依附从一而终!)

参数传递上 这才是促使我写这篇博文的动机,再次感谢 Zhang ..... 到底什么时候需要用指针,什么时候用引用,引用,指针到底怎么用...Orz..

举例,经典的值交换例程:交换a,b两个变量的值

Code_1 值传递

#include <iostream>#include <string>using namespace std;void swap_self(int n, int m){cout << "verify varibale address:"<<&n << " " <<&m << endl;int temp = n;n = m;m = temp;}void main(void){int a = 10; int b = 20;cout <<"before swap:"<< &a<<" "<< &b << endl;swap_self(a, b);cout << "after swap:" << &a << " " << &b << endl;cout << "after swap:" << a << " " << b << endl;}

从运行结果上可以看出,其变量之间的值并未被交换,交换前a,b变量的地址与n,m的地址并不相同,说明形参传入的是实参的一个copy,被调函数的形式参数作为被调函数的局部变量处理,即在栈中开辟了内存空间以存放由主调函数放进来的实参的值,从而成为了实参的一个副本。所以copy值的改变并不能改变实参,所以,当函数内部需要修改参数,并且不希望这个改变影响调用者时,采用值传递

Code_2_1 指针传递_1

#include <iostream>#include <string>using namespace std;void swap_self(int *n, int *m){int *temp = n;n = m;m = temp;cout << "verify varibale value:" << *n << " " << *m << endl;}void main(void){int a = 10;int b = 20;cout << "before swap:" << &a << " " << &b << endl;swap_self(&a, &b);cout << "after swap:" << &a << " " << &b << endl; //输出a,b的地址cout << "after swap:" << a << " " << b << endl;}

其变量之间的值仍然未被交换,但函数内部变量值完成交换,指针传递参数本质上是值传递的方式,它所传递的是一个地址值。指针传递参数本质上是值传递的方式,它所传递的是一个地址值,本质上,他是实参的copy进行操作,一旦函数调用结束,栈被自动销毁,函数所操作的对象随即消失,所以不能交换实参值。难道我记错了!记得指针是可以实现操作实参的呀,怎么不行看呢???请看下面的实例

Code_2_2 指针传递_2

#include <iostream>#include <string>using namespace std;void swap_self(int *n, int *m){int temp = *n;*n = *m;*m = temp;}void main(void){int a = 10;int b = 20;cout <<"before swap:"<< &a<<" "<< &b << endl;swap_self(&a, &b);cout << "after swap:" << &a << " " << &b << endl;cout << "after swap:" << a << " " << b << endl;}

成功实现了变量之间值的交换,函数形参传入的是实参的地址,函数内部操作的对象是指针指向的内存即实参,所以能实现值交换。

Code_3 引用传递

#include <iostream>#include <string>using namespace std;void swap_self(int &n, int &m){cout << "verify varibale address:" << &n << " " << &m << endl;int temp = n;n = m;m = temp;}void main(void){int a = 10;int b = 20;cout << "before swap:" << &a << " " << &b << endl;swap_self(a, b);cout << "after swap:" << &a << " " << &b << endl;cout << "after swap:" << a << " " << b << endl;}

漂亮,可以看出,swap_self 中变量n,m的地址就是变量a,b的地址,函数也成功实现值交换,引用传递中形参相当于是实参的“别名”,对形参的操作其实就是对实参的操作,在引用传递过程中,被调函数的形式参数虽然也作为局部变量在栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参的任何操作都被处理成间接寻址,即通过栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做的任何操作都影响了主调函数中的实参变量。


0 0