2014-06-18

2.2 调用(invoking)一个函数

  2.2.1 Pass by Reference语义

    在函数swap的参数中使用reference和pointer

    pointer参数和reference参数的差异和用法

2.4 使用局部静态对象(Local Static Objects)

2.5 声明一个inline函数

2.7 定义并使用Template Functions (模板函数)

2.8 函数指针(Pointers to Functions)带来更大的弹性

  函数指针和指针函数区别

2.9 设定头文件(Header Fiels)

 

2.2 调用(invoking)一个函数


 返回

2.2.1 Pass by Reference语义

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

 1 #include <iostream>
 2 using namespace std;
 3  
 4 int main()
 5 {
 6     int ival=1024;  //对象,型别为int
 7     int *pi=&ival;  //pointer(指针),指向一个int对象
 8     int &rval=ival; //reference(化身),代表一个int对象
 9 
10     //这里不是令rval改为代表jval对象,而是将jval赋值给rval所代表的对象(也就是ival)。
11     int jval=4096;  
12     rval=jval;     
13 
14     ival =2048;
15     pi;
16     //这里不是令pi指向rval对象,而是将ival(此为rval所代表之对象)的地址赋给pi
17     pi=&rval;
18 
19     return 0;
20 }

《Essential C++》读书笔记 之 面向过程编程风格


重点是:面对reference的所有操作都像面对“reference所代表的对象”所进行的操作一样。

在函数swap的参数中使用reference和pointer

当我们以reference作为函数参数时,情况是一样的,如下代码所示:

 1 #include <iostream>
 2 void swap(int &, int &);
 3 
 4 int main()
 5 {
 6     int v1=1;
 7     int v2=2;
 8     swap(v1,v2);
 9 
10     v1;
11     v2;
12 
13     return 0;
14 }
15 
16 void swap(int &val1, int &val2)
17 {
18     int temp=val1;
19     val1=val2;
20     val2=temp;
21 }


运行结果如下图所示:

《Essential C++》读书笔记 之 面向过程编程风格

 

 将参数声明为reference的理由有两个:

  • 希望直接对所传入的对象进行修改;
  • 为了降低复制大型对象的负担。

如果我们愿意,也可以将参数以pointer形式传递。这和以reference传递的效用相同:传递的是对象地址,而不是整个对象的复制品。唯一的差别是他们的用法不同。如下代码所示:

 

 1 #include <iostream>
 2 
 3 void swap(int *,int *);
 4 
 5 int main()
 6 {
 7     int v1=1;
 8     int v2=2;
 9     swap(&v1,&v2);
10 
11     v1;
12     v2;
13 
14     return 0;
15 }
16 
17 
18 void swap(int *val1, int *val2)
19 {
20     int temp=*val1;
21     *val1=*val2;
22     *val2=temp;
23 }

但如果swap方法改成如下,变量v1,v2不会调换:

1 void swap(int *val1, int *val2)
2 {
3     int *temp=val1;
4     val1=val2;
5     val2=temp;
6 }

因为上述方法只是更改了指针本身的地址,如下图:

《Essential C++》读书笔记 之 面向过程编程风格

pointer参数和reference参数的差异和用法

pointer可能(也可能不)指向一个实际对象。当我门提领pointer时,一定要先确定其值并非为0。至于reference则必定会代表某个对象。

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

2.4 使用局部静态对象(Local Static Objects)


 返回

fibon_seq()函数是这样一个函数,每次调用时,会计算出Fibonacci数列(元数数目由用户指定),并以一个vector存储计算出来的元素值,然后返回。代码如下:

 1 vector<int> fibon_seq( int size )
 2 {
 3    if ( size <= 0 || size > 1024 )
 4    {
 5         cerr << "Warning: fibon_seq(): "
 6              << size << " not supported -- resetting to 8\n";
 7           size = 8;
 8     }
 9 
10    vector<int> elems( size );
11 
12    for ( int ix = 0; ix < size; ++ix )
13            if ( ix == 0 || ix == 1 )
14                   elems[ ix ] =  1;
15             else elems[ ix ] =  elems[ix-1] + elems[ix-2];
16 
17    return elems;
18 }

以上代码有一个问题:每次调用时,都要重新计算。
我们希望,保存已经计算出来的元素。上面代码的局部变量肯定不行。如果将vector对象定义于file scope之中,又过于冒险,它会打乱不同函数之间的独立性,使它们难以理解。

本例的另一个解法便是使用局部静态对象:

 1 #include <iostream>
 2 #include <string>
 3 #include<vector>
 4 using namespace std;
 5 
 6 //定义函数
 7 const vector<int> *fibon_seq( int);
 8 
 9 int main()
10 {
11     fibon_seq( 5 );
12     fibon_seq( 4 );  //前4个element都已计算,不会重复计算
13     fibon_seq( 6 );  //只计算还没有计算出来的第6个element
14 
15     return 0;
16 }
17 
18 const vector<int> *fibon_seq( int size )
19 {
20     const int max_size = 1024;
21     static vector< int > elems;
22 
23     if ( size <= 0 || size > max_size ){
24         cerr << "fibon_seq(): oops: invalid size: "
25             << size << " -- can’t fulfill request.\n";
26         return 0;
27     }
28 
29     // if size is equal to or greater than elems.size(),
30     // no calculations are necessary ... 
31     for ( int ix = elems.size(); ix < size; ++ix ){
32         if ( ix == 0 || ix == 1 )
33             elems.push_back( 1 );
34         else elems.push_back( elems[ix-1]+elems[ix-2] );
35     }
36 
37     return &elems;
38 }
View Code

相关文章:

  • 2021-11-26
  • 2021-05-24
  • 2021-12-23
  • 2021-05-26
  • 2021-05-01
  • 2021-11-17
  • 2022-02-18
  • 2021-06-11
猜你喜欢
  • 2022-02-15
  • 2021-06-24
  • 2021-11-24
  • 2021-09-27
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案