内联函数
原理
编译的最终产品是可执行程序——由机器语言组成。运行程序时,每条指令都有特定的存储地址,程序在调用函数时会来回跳跃并记录跳跃地址。内联函数提供了另一种选择,编译器将使用相应的函数代码替换函数调用。内联函数的运行速度比常规函数快,但代价是需要占用更多内存。
如果执行函数代码的时间比处理函数调用机制的时间长,则节省时间不多。如果代码处理时间很短,内联调用就可以节省很多时间。
用法
在函数声明前加上关键字inline
在函数定义前加上关键字inline
#include<iostream>
inline double square(double x){return x*x;}
int main()
{
using namespace std;
double a,b;
cout<<"a= "<<square(5.0)<<" b= "<<square(3.5+2.5);
}
内联函数和常规函数一样,也是按值来传递参数的
引用变量
创建引用变量
int a;
int &A=a;
上述声明允许将A和a互换——它们指向相同的值和内存单元
需要注意:上述语句中的&不是地址运算符,而是将A的类型声明为Int &,即指向int变量的引用。
但下述语句中的&是地址运算符,其中&A表示A引用变量的地址
cout<<"A's address= "<<&A;
必须在声明引用时将其初始化,一旦于某个变量关联起来就将一直效忠于它
将引用用作函数参数
按引用传递允许被调用函数直接访问调用函数中的变量,在C语言中相应采用按指针传递的方式。
#include<iostream>
inline double square(double &x)
{
x=10.0;
return x*x;
}
int main()
{
using namespace std;
double a=5.0;
cout<<square(a)<<endl;
cout<<a;
}
可以发现a的值被改变,即被调用函数直接访问了a
将引用用于结构
使用结构引用参数只需在声明结构参数时使用引用运算符&即可,我们看如下代码
#include<iostream>
#include<string>
using namespace std;
struct A{
std::string name;
int data;
};
void founc1(A& a)
{
a.data++;
}
A& founc2(A& a)
{
a.data++;
return a;
}
void display(const A& a)
{
cout<<a.name<<" "<<a.data<<endl;
}
int main()
{
A one={"apple",10};
display(one);
founc1(one);
display(one);
display(founc2(one));
}
其中,display函数不修改结构中的值,因此我们使用一个const引用参数。
需要注意的是founc2是一个返回引用的函数,那么为什么要返回引用呢?
A two=founc2(one);
如果按值返回的话会把整个结构复制到一个临时位置,再将这个拷贝复制给two。但在返回引用时将直接把one复制到two,其效率更高。
返回引用时需注意避免返回函数终止时不再存在的内存单元引用
const A& founc2(A& a)
{
A newstruct;
newstruct=a;
return newstruct;
}
该函数返回一个指向临时变量的引用,函数运行完毕后它将不再存在。
默认参数
默认参数指的是当函数调用中省略了实参时自动使用的一个值,如果将wow(int n)设置成n有默认值1,则函数调用wow(1)相当于wow(1)。
设置默认值必须通过函数原型,且需注意必须从右向左添加默认值。也就是说要为某个参数设置默认值,则必须为它右边所有参数提供默认值
int wow1(int n,int m=4,int j=5)//valid
int wow2(int n,int m=4,int j)//invalid
int wow3(int n=1,int m=4,int j=5)//valid
函数重载
函数重载允许我们使用多个重名的函数,其关键在于函数的参数列表——也称为函数特征标。
可以定义一组原型如下的print()函数:
void print(const char* str,int width);
void print(double d,double data);
void print(long i);
使用print()函数时,编译器将根据所采用的用法使用有对应特征标的原型
需注意编译器将把类型引用和类型本身视为同一个特征标
如:
double cube(double x);
double cube(double& x);
在执行时会产生错误
请不要滥用函数重载,仅当函数基本上执行相同的任务但使用不同的参数类型时才采用函数重载。
函数模板
建立函数模板
函数模板是通用的函数描述,即它们使用泛型来定义函数,其中的泛型可用具体的类型替换。
template <typename AnyType>
void Swap(Anyype &a,AnyType &b)
{
AnyType temp;
temp=a;
a=b;
b=temp;
}
可以用class对typename进行替换,即:
重载的模板
需要对多个不同类型使用同一种算法的函数时可以使用模板,但并非所有的类型都使用相同的算法。为满足这种需求,可以像重载常规函数那样重载模板定义。
template <typename T>
void Swap(T &a,T &b);
template <typename T>
void Swap<T *a,T*b,int n>;//用于交换数组
显示具体化
不深究