C++ Primer Plus 随记(第八章)函数探幽

1、内联函数:编译器将使用相应的代码替换函数调用。  --优点:运行速度稍快  --缺点:代码膨胀

内联函数:一、在函数声明前加上关键字inline;二、在函数定义前加上关键字inline。

无法作为内联函数的原因:一、内联函数不能递归;二、函数体过大。

内联与宏: C语言使用预处理器语句 #define 提供宏--内联代码的原始实现(实际上使用 文本替换来实现)。   

#define SQUARE(X)  ((X)*(X));          使用c语言的宏执行可以考虑利用C++内联函数进行替换。(函数宏具有局限性)

2、引用变量:已定义变量的别名,可以交替使用本名和别名对该变量操作。

int  rats =101;           int & randents = rats;         // 创建引用变量         

randents  = bunnies;        // 该语句会同时将 bunnies 的值赋值给  randents 和  rats(两者的物理地址本质上相同)

 引用变量必须在声明时进行初始化

int & randents = rats;   int * const  pr = & rats;   其中  randents  //  等价于   *pr

3、引用(左值引用)传参 ,引用传参对于较大的变量有利于节约时间,但是同样相对严格。

double cube(double a);

double refcube(double & a);        // 可能会修改对应的参数,若不允许修改   double refcube(const double & a); // 不可修改左值。

 double x=2.0;          cube(x+1);    // pass      对应的          refcube(x+1);   // not pass

 上述左值参数是可被引用的数据对象:变量、数组元素、结构成员、引用、解除引用的指针。   右值参数:字面常量、包含多项的表达式。

在引用参数为const时,编译器同样也可能产生临时变量:

一、实参的类型正确,但不是左值;二、实参的类型不正确,但可以转换为正确的类型。

尽可能将引用参数声明为const:一、避免无意中修改数据(const参数 和 const 返回值);二、可以同时接受const和非const参数;三、函数可以正确生产并使用临时变量。

右值引用:  double && rref = std::sqrt(36.0);    

对象、继承、引用:  基类引用参数,可以接受基类对象和派生类对象作为参数。

4、何时引用参数

原因①、程序员能够修改调用函数中的数据对象;②传递引用可以体提高程序运行速度。

对象特征数据对象很小数组较大结构类对象
传递方式按值传递指针const指针或引用const引用

5、默认参数:

int harpo(int n, int  m, int j=5);   // 调用  harpo(1,2); harpo(1,2,3); 都可以。    默认参数必须在最后。

6、函数重载(函数多态):多个同名的函数,其函数参数列表(函数特征标)。

参数数目、函数类型、参数排列顺序。           其中const 参数 可以接受const参数和非const参数,而非const参数仅接受非const参数。

多个匹配的函数重载,将会调用最优匹配项。

7、函数模板-可以使用泛型来定义函数,其中的泛型可用具体的类型。

①template <typename AnyType>          // typename 可以替换为 class

void swap(AnyType  &a, AnyType &b) {...}       // 模板版本

上述模板没有创建任何函数,在调用时编译器会根据参数定义相应的函数。     模板可以重载

模板的局限性:可能无法处理某些类型(通用化有时并没有意义)。    上述AnyType为数组时,其中的赋值可能无法使用(除非加上对应的重载)

②template<>  void swap<job>(job &, job &);   //上述模板函数的特化版本(显式具体化)  等价于 template<>  void swap(job &, job&);

③void swap(job &, job&)                                 // 非模板版本

 上述三个版本的函数,针对job类型的函数, 匹配程度为 ③>②>①。

8、具体化(显式实例化、隐士实例化、显式具体化)

显式实例化:

template<class T>  void add(T a, T b){};     

int x=8;doubley=9;   add<double>(x,y);  //将x 从int 显式转化为double ,然后进行double类型实例化;

 swap<double>(x,y); // 不可行,swap模板使用引用参数,不可行。

9、函数版本匹配

顺序:完全匹配(常规函数 优于 模板)>提升转换(char->int;float->double)>  标准转换(char->int;long->double)>用户定义的转换

完全匹配   volatile关键字:保证每个线程能够获取该关键字修饰变量的最新值,从而避免出现数据脏读(旧值)的现象。

实参      type          type&        type[]     type       type               type                     type*             type*

形参      type&       type           *type      type*     const type      volatile type        const type      volatile type

10、关键字 decltype(类型推断)

decltypeauto都可以用来推断类型,但是二者有几处明显的差异:

  1. auto忽略顶层const,decltype保留顶层const;

  2. 对引用操作,auto推断出原有类型,decltype推断出引用;

  3. 对解引用操作,auto推断出原有类型,decltype推断出引用;

  4. auto推断时会实际执行,decltype不会执行,只做分析。总之在使用中过程中和const、引用和指针结合时需要特别小心。

template<class T1, class T2>

auto do(T1 x,T2 y) -> decltype(x+y){              // decltype(x+y)   其中的 x+y 表示根据最后的返回值推断类型

              return x+y;

}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值