1.当我们调用一个函数时,会在内存中建立起一块特殊区域,称为“程序栈”,这块特殊区域提供了每个函数参数的存储空间,它也提供函数所定义的每个对象的内存空间--我们将这些对象称为局部对象。一旦函数完成,这块内存就会被释放掉,或者是说从程序堆栈中被pop出来。
2.Pass by Reference语意
reference扮演着外界与对象之间的一个间接号码牌的角色,只要在型别名称和reference名称之间插入&符号,便是声明了一个reference:
1 int ival=1024; //对象,型别为int2 int *pi=&ival; //pointer(指针),指向一个int对象3 int &rval=ival; //reference(化身),代表一个int对象
当我们这么写:
1 int jval=4096;2 rval=jval;
时,便是将jval赋值给rval所代表的对象(也就是ival).我们无法rval改为代表jval,因为C++不允许我们改变reference所代表的的对象,它们必须从一而终,当我们写:
1 pi=&rval;
时,我们其实是将ival(此为rval所代表的之对象)的地址赋值给pi.我们并未令pi指向rval.注意,重点是面对reference的所有操作都像面对“reference 所代表之对象”所进行的操作一般无二。当我们以reference作为函数参数时,亦复如此。
当swap()函数将val2赋值给val1:
1 void swap()2 {3 //实际参数的值会因而改变4 int temp=val1;5 val1=val2;6 val2=temp;7 }
时,的确是将vec[jx]赋值给vec[ix]--前者是val2所代表的之物,后者是val1所代表的之物:
1 swap(vec[ix],vec[jx]);
当我们以by reference 方式传递对象当做函数参数,对象本身并不会复制出另一份——复制的是对象的地址。函数中对该对象进行的任何操作,都相当于是对传入的对象进行间接操作。
将参数声明为reference的理由之一是,希望得以直接对所传入的对象进行修改。这个理由极为重要,因为就像我们在前面的例子中所见,不这么做的话,程序无法正确运行。
将参数声明为reference的第二个理由是,为了降低复制大型对象的负担。这个理由相较起来不那么重要,因为对程序而言不过是效率议题罢了。
3.举个例子,现在我将打算显示的vector以传值方式传入display()中,这意味着每当我想进行显示操作时,vector内的所有元素都会被复制。这并不会造成错误,但是如果直接传入vector地址,速度会更快。将vector的参数声明为reference,便可达到这个目的。
1 void display(const vector &vec)2 {3 for(int ix=0;ix
我们声明了一个 reference to const vector ,因为函数之中并不会更改vector的内容,少了const并不会造成错误,但加上const可以让阅读程序的人了解,我们以传址的方式来传递vector,为的是避免重复操作,而不是为了要在函数之中对它进行修改。
如果我们愿意,也可以将vector以pointer的形式传递。这和以reference传递的效用相同:传递的是对象的地址,而不是整个对象的复制品。唯一的差别在于reference和pointer的用法不同,例如:
1 void display(const vector *vec) 2 { 3 if(!vec) 4 { 5 cout<<"display():the vector pointer is 0\n"; 6 return ; 7 } 8 9 for(int ix=0;ixsize();++ix)10 {11 cout<<(*vec)(ix)<<" ";12 cout<
1 int main()2 {3 int ia[8]={ 1,2,1,12,2,2,1,1};4 vector vec(ia,ia+8);5 6 cout<<"vector before sort";7 display(&vec);//传入地址8 // 其余代码9 }
pointer参数和reference 参数二者之间更重要的差异是,pointer可能(也可能不)指向某个实际对象,当我们提领pointer时,一定要先确定其值并非0.至于reference则必定会代表某个对象,所以不需要做此检查。
一般来说,除非你希望在函数内更改参数值,否则在传递内建型别时,不要使用传址方式,传址方式主要是作为传递class object 之用。