语言基础-函数

参数传递

将引用作为函数参数的特点:

  • 在被调函数中对形参变量的操作就是对其相应的目标对象的操作。
  • 在内存中没有产生实参的副本,它是直接对实参进行操作;而使用一般变量传递函数的参数,当发生函数调时,需要给形参分配存储单元,如果传递的是对象,还要调用拷贝构造函数。因此,当参数传递的数据较大时,用引用比用一般的变量传递参数的效率和所占空间都好。
  • 虽然使用指针也能达到引用的效果,但是在函数调用时同样要给形参分配存储单元,而且程序容易产生错误,阅读性差。

传递指针的引用

例子:

void ptrswap(int *&v1, int *&v2){
  int *tmp = v2;
  v2 = v1;
  v1 = tmp;
}

形参int *&v1的定义从右往左理解:v1是一个引用,与指向int类型对象的指针相关联。也就是说,v1只是传递进ptrswap函数的任意int型指针的别名。

内联函数

用inline修饰,有两种形式:

  • 在类中定义的成员函数全部默认为内联函数,可以显示地加上inline标识符,或者不加。
  • 普通函数声明或定义前加上inline成为内联函数。

在编译时,调用内联函数的地方,将不进行函数调用,而是使用函数体替换调用处的函数名,形式类似宏替换,这种替换成为内联扩展,可以消除函数调用时的时间开销。

注意,宏定义与内联函数的区别:1. 宏定义是在预处理阶段进行代码替换,而内联函数是在编译阶段插入代码;2. 宏定义没有类型检查,而内联函数有类型检查。

函数重载

函数重载用来命名一组功能相似的函数,这样减少函数名的数量,避免名字空间的污染。

函数重载,同名,参数个数不同,或参数类型不同,不能仅仅基于不同的返回类型而重载。

函数模板与泛型

泛型编程与面向对象编程一样,有依赖于每种形式的多态性。模板是泛型的基础。

例子:模板加内联

#include <iostream>
using namespace std;

template <typename T>
inline T AddNums(const T &a, const T &b){
    return a + b;
}
int main()
{
    cout << AddNums(3, 5) << "," << AddNums(3.2, 5.3) << endl;

    return 0;
}

例子:类模板

template <class Type> class Queue {
public:
    Queue();
    void push(const Type &);
private:
    // ...
};

使用类模板时,必须为模板形参显示制定实参。Queue<int> q;

函数的递归

递归必须满足两个条件:

  • 递归表达式(递归体)
  • 边界条件(递归出口)

递归的精髓在于能否将原始问题转换为属性相同但规模较小的问题。

递归的优点是减少程序的代码量,缺点是通常情况下效率不高。

例:斐波那契递归实现

int Fib(n) {
  if(n == 0)
    return 0;
  else if(n == 1)
    return 1;
  else
    return Fib(n-1)+Fib(n-2);
}

将递归转换为非递归,通常需要借助来实现。

附:斐波那契动态规划实现

int DPFib(int n){
    int ret = 0,dpA, dpB;
    if(n==1)
        return 1;
    else if(n==2)
        return 2;
    dpA = 1;
    dpB = 2;
    for(int i = 3; i <= n; ++i){
        ret = dpB + dpA;
        dpA = dpB;
        dpB = ret;
    }
    return ret;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值