C++学习笔记2:函数探幽

《C++ Primer Plus》第八章:函数探幽

1.内联函数

1.1 内联函数机制

常规函数将程序流程转到独立的函数,内联函数用内联代码替换函数调用。内联函数的运行速度比常规函数稍快,但占用更多内存。如果在程序的10个地方调用了同一个内联函数,则该程序将包含该函数代码的10个副本。

1.2 语法

使用关键字inline,通常省略原型,将整个定义放在本应提供函数原型的地方

inline double square(double x){return x*x;}

2. 引用变量

2.1 创建引用变量

int rats;
int & rodents = rats;
rodents作为rats的别名,它们指向相同的值和内存地址。声明引用时必须将其初始化,之后不能再对其赋值。

2.2 将引用用作函数参数

一般用于结构和类。

2.3 引用的属性和特点

double cube(double a){return a*=a*a;}
double refcube(double & a){return a*=a*a;}
double refbuc1(const double & a){return a*a*a;}
double x = 4.0;
double re1 = cube(x+5);
double re2 = refcube(x+5);  //wrong
double re3 = refcube(x+5);  //create temporary variable
如果想让函数使用传递给它的信息,而不对这些信息进行修改,同时又想使用引用,则应使用常量引用。

对传递给引用参数的实参类型限制比较严格,如上代码,不能将表达式传递给引用参数。

但如果是常量引用参数,将生成临时变量。

2.4 返回引用

返回引用时不需要先将结果复制到一个临时位置,再将结果复制给接收返回结果的变量,而是直接将结果复制到接收返回结果的变量。

注意:避免返回函数终止时不再存在的内存单元引用,一般返回一个作为参数传递给函数的引用,或者用new来分配新的存储空间。如下代码。

const double & clone1(double & ft)
{
  double re;
  re = ft;
  return re;
}
const doubel * clone2(double & ft)
{
  double * re;
  *re = ft;
  return *re;
}

3. 默认参数

对于带有参数列表的函数,要为某个参数设置默认值,则必须为它右边的所有参数提供默认值。因为实参按从左到右的顺序依次赋给相应的形参,而不能跳过任何参数。只有函数原型指定默认值,函数定义与没有默认参数时完全相同。

4. 函数重载

4.1 定义

函数的参数列表(特征标)相同,即参数数目、类型、排列顺序相同,则为函数重载。

4.2 注意

编译器在检查特征标时,将类型引用和类型本身视为同一个特征标。

是特征标而不是函数类型使得可以对函数进行重载,如下两个声明是互斥的。

long gronk(int n,float m);
double gronk(int n,float m);

5. 函数模板

5.1 语法

在标准C++98添加关键字typename之前,C++使用关键字class创建模板。现在使用typename和class均可。

并非所有的模板参数都必须是模板参数类型。

一般讲函数模板放在头文件中,在需要使用函数模板的文件中包含头文件。

template 
   
   
    
    
void swap(T & a,T & b)
{
  T temp;
  temp =a;
  a = b;
  b = temp;
}
template 
    
    
     
     
void swap(T & a,T & b)
{
  T temp;
  temp =a;
  a = b;
  b = temp;
}
    
    
   
   

5.2 显示具体化

编写的函数模板很可能无法处理某些类型,为这些类型编写的函数模板的具体版本为显示具体化。
编译器在选择原型时,非模板版本>显示具体化>函数模板。

struct job
{
char name[40];
double dalary;
int floor;
};
void swap(job &, job &);
template 
    
    
     
     
void swap(T &, T &);
template <> void swap
     
     
      
      (job &, job &);  //显示具体化方法一
template <> void swap(job &, job &);      //显示具体化方法二
     
     
    
    

5.3 显示实例化

在代码中包含函数模板本身不会生成函数定义,编译器使用模板为特定类型生成函数定义时,得到的是模板实例。模板的实例化分为隐式实例化和显示实例化。
template 
     
     
      
       void swap(T &, T &);
swap(a,b);  //隐式实例化
template void swap
      
      
       
       (a,b);  //显示实例化
      
      
     
     

5.4 关键字decltype

如下代码中a+b的类型无法确定,只知道跟(a+b)的类型相同。
template 
     
     
      
      
void ft(T1 a,T2 b)
{
  ...
  decltype(x+y) xpy = x + y;
  ...
}
     
     

关键字decltype表示变量var的类型和括号中的expression的类型相同。注意:如果expression是由括号扩起的标识符,则var为指向其类型的引用。
decltype (expression) var;

5.5 C++11后置返回类型

auto h(int x,float y) ->double
{/*function body*/};
template
      
      
       
       
auto get(T1 x,T2 y) ->decltype(x+y)
{
  ...
  return x+y;
}
      
      








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值