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