Essential C++学习笔记

1.当我们调用一个函数时,会在内存中建立起一块特殊区域,称为“程序栈”,这块特殊区域提供了每个函数参数的存储空间,它也提供函数所定义的每个对象的内存空间--我们将这些对象称为局部对象。一旦函数完成,这块内存就会被释放掉,或者是说从程序堆栈中被pop出来。

2.Pass by Reference语意

reference扮演着外界与对象之间的一个间接号码牌的角色,只要在型别名称和reference名称之间插入&符号,便是声明了一个reference:

1 int ival=1024;   //对象,型别为int
2 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<int> &vec)
2 {
3 for(int ix=0;ix<vec.size();++ix)
4 {
5 cout<<vec[ix]<<" ";
6 cout<<endl;
7 }
8 }

我们声明了一个 reference to const vector ,因为函数之中并不会更改vector的内容,少了const并不会造成错误,但加上const可以让阅读程序的人了解,我们以传址的方式来传递vector,为的是避免重复操作,而不是为了要在函数之中对它进行修改。

如果我们愿意,也可以将vector以pointer的形式传递。这和以reference传递的效用相同:传递的是对象的地址,而不是整个对象的复制品。唯一的差别在于reference和pointer的用法不同,例如:

 1 void display(const vector <int> *vec)
 2 {
 3       if(!vec) 
 4       {
 5         cout<<"display():the vector pointer is 0\n";
 6         return ;
 7 }
 8 
 9 for(int ix=0;ix<vec->size();++ix)
10 {
11        cout<<(*vec)(ix)<<" ";
12        cout<<endl;
13 }
1 int main()
2 {
3    int ia[8]={1,2,1,12,2,2,1,1};
4    vector<int>  vec(ia,ia+8);
5 
6    cout<<"vector before sort";
7    display(&vec);//传入地址
8    // 其余代码
9 }

pointer参数和reference 参数二者之间更重要的差异是,pointer可能(也可能不)指向某个实际对象,当我们提领pointer时,一定要先确定其值并非0.至于reference则必定会代表某个对象,所以不需要做此检查。

一般来说,除非你希望在函数内更改参数值,否则在传递内建型别时,不要使用传址方式,传址方式主要是作为传递class object 之用。

 

posted @ 2018-05-11 10:41  sgggr  阅读(506)  评论(0编辑  收藏  举报