任何东西都可以凝固

导航

引用参数(引用传递)、调用参数(值传递)、 内存分配

函数参数传递机制

  堆栈存储区是主调函数(过程)和被调用函数(过程)在调用发生时进行通信的主要区域。
  基本的参数传递机制有两种:值传递和引用传递。

值传递(passl-by-value): 被调函数的形式参数作为被调函数的局部变量处理,即在堆栈中开辟了

内存空间以存放由主调函数放进来的实参的值,从而成为了实参的一个副本。值传递的特点是被调

函数对形式参数的任何操作都是作为局部变量进行,不会影响主调函数的实参变量的值。

引用传递(pass-by-reference):被调函数的形式参数虽然也作为局部变量在堆栈中开辟了内存空间

,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参的任何操作都被处理成

间接寻址,即通过堆栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做

的任何操作都影响了主调函数中的实参变量。

引用概念

      定义引用使用&符号。引用只在C++中可以使用,C中没有引用的概念。

      引用等于是对象的另一个名字,与原对象一模一样,并都指向同一块内存地址。

  1. int a = 5;  
  2. int & b = a;  
int a = 5;
int & b = a;

      这里定义了引用b,它就是a的一个别名,那么a=6和b=6效果是一样的。
      定义引用时应注意:

            1).  定义引用是必须给它初始化,并且不能初始化NULL,int &b;这样的定义是不正确的。

            2).  引用并不是对象的拷贝,也不是指针。

            3).  &这里并不是取地址,它只是代表引用。

           4).   引用不是一种数据类型,所以没有引用的引用,没有引用的指针

 

引用参数不需要用malloc为其申请空间;调用参数可以用malloc为其申请空间方便在被调函数中使用。

实例:

修改指针参数的地址,(区分2级指针)

  int m=10;
  int*n=&m;
  void swap(int*&a)  
  {    
     a=n;   //a地址被n替换
  }    
/******
值传递 的参数有2种--指针变量和非指针变量。当形参为指针变量的时候,要区分于引用传递,指

针变量 通过值传递过来的是一个地址的值,在被调函数中,只是修改了内存地址中存放的值,而并

没有修改地址值。

int swap(int *x,int *y)

{

 int temp;

temp=*x;*x=*y;*y=temp;

}

main()

{ int a=1,b=2;

int *p1=&a;*p2=&b;

swap(p1,p2);}

 

函数swap以两个指针变量作为参数,当main()调用swap时,是以值传递的方式将指针变量p1、p2的值(也就是变量a、b的地址)放在了swap在堆栈中为形式参数x、y开辟的内存单元中。这一点从以下的汇编代码可以看出(注释是笔者加的):  

 

阅读上述代码要注意,INTEL80x86系列的CPU对堆栈的处理是向下生成,即从高地址单元向低地址单元生成。从上面的汇编代码可知,main()在调用swap之前,先将实参的值按从右至左的顺序压栈,即先p2进栈,再p1进栈。调用结束之后,主调函数main()负责清理堆栈中的参数。

 

  C++既有C的值传递又有引用传递。在值传递上与C一致,这里着重说明引用传递。如本文前面所述,引用传递就是传递变量的地址到被调函数使用的堆栈中。在C++中声明引用传递要使用"&"符号,而调用时则不用。下面的代码是使用引用传递的swap2函数和main函数

  1. int& swap2(int& x, int& y)  
  2. {  
  3. int temp;  
  4. temp = x;  
  5. x = y;  
  6. y = temp;  
  7. return x;  
  8. }  
  9. void main()  
  10. {  
  11. int a = 1, b = 2;  
  12. swap2(a, b);  
  13. }  

 

 

swap2与前面的swap函数的汇编代码是一样的。这是因为前面的swap函数接受指针变量,而指针变量的值正是地址。所以,对于这里的swap2和前面的swap来讲,堆栈中的函数参数存放的都是地址,在函数中操作的方式是一致的。但是,对swap2来说这个地址是主调函数通过将实参变量的偏移地址压栈而传递进来的--这是引用传递;而对swap来说,这个地址是主调函数通过将实参变量的值压栈而传递进来的--这是值传递,只不过由于这个实参变量是指针变量所以其值是地址而已。
  这里的关键点在于,同样是地址,一个是引用传递中的变量地址,一个是值传递中的指针变量的值。我想若能明确这一点,就不至于将C语言中的以指针变量作为函数参数的值传递情况混淆为引用传递了。
  虽然x是一个局部变量,但是由于其值是主调函数中的实参变量的地址,故在swap2中返回这个地址是合法的。

 另外关于存储数据方面,一般是将局部变量,函数返回地址,函数参数放到堆栈中,而函数返回值一般放到寄存器中,为的是方便中断,如果有零时中断就可以直接从寄存器中处理,不用再进行压栈出栈操作。

 

posted on 2016-10-29 17:26  任何东西都可以凝固  阅读(565)  评论(0)    收藏  举报