C++ 第8章 函数探幽

第8章 函数探幽

本章内容包括:
  • 内联函数
  • 引用变量
  • 如何按引用传递参数
  • 默认参数
  • 函数重载
  • 函数模板
  • 函数模板具体化
一 函数的内联:

内联函数是C++为提高程序运行速度所做的一项改进。常规函数与内联函数的主要区别在于编译器如何将它们组合到程序中。

内联函数是将函数替换在相应的位置,而常规函数是使用时进行跳转。内联函数比常规函数执行效率稍微高一点,但是占用的内存也多了。

应有选择的使用内联函数。当执行代码的时间比处理函数调用机制的时间长,则节省的时间很少。另一方面,因为这一过程的时间非常短,所以节约的总时间并不多。除非函数经常被调用

使用方法

  • 在函数声明前加上inline
  • 在函数定义前加上inline
二 引用变量:

引用是已定义变量的别名。主要用途是用作函数的形参。通过将引用变量作为形参,函数将使用原始数据,而不是其副本。这样除指针以外,引用也作为函数处理大型结构的一种方便的途径

使用方法:

inline void add(int &a){a++;};

int main(int argnum,char *args[]) {
    int rate = 3;
    add(rate);
    cout << rate;
    return 0;
}

引用更接近const 指针,必须在创建时进行初始化,一旦与某个变量关联起来,就将一直效忠于它。

临时变量、引用变量与const:

如果实参与引用参数不匹配,c++将生成临时变量。当前,仅当参数为const引用时c++才允许这样做。

生成临时变量的条件:
  • 引用参数是const
  • 实参类型正确,但不是左值,或类型不正确,但能转换成正确的类型。

当类型不匹配时,编译器将产生临时变量去进行计算,并将改变反应在临时变量中。如果不是const类型,将失去使用引用变量的意义

将引用用于结构:

引用非常适合用于结构和类,使用方法与基本类型引用相同

#include <iostream>
#include <string>

using namespace std;

struct free_throws{
    std::string name;
    int mid;
};

void display(const free_throws & ft);
void set_pc(free_throws & ft);
free_throws & accmulate(free_throws & target, const free_throws & source);

int main(int argnum,char *args[]) {

    free_throws one{"one", 12};
    free_throws two{"two", 20};
    set_pc(one);
    display(accmulate(one,two));
    return 0;
}

void display(const free_throws & ft){
    cout << ft.name << endl;
    cout << ft.mid << endl;
}
void set_pc(free_throws & ft){
    ft.mid += 100;
}
free_throws & accmulate(free_throws & target, const free_throws & source){
    target.name += " " + source.name;
    target.mid += source.mid;
    return target;
}
三 默认参数:
char * left(const char * str, int n = 1 )
对于多个参数,必须从左到右添加默认值。
四 函数重载:

函数多态是C++在C语言上的新功能。默认参数能使用不同数目的参数调用相同的函数。而多态则可以使用多个同名参数。

函数重载的关键是函数的参数列表----也称为函数特征标。如果两个函数的参数数目和类型相同,同时参数的排序顺序也相同,则它们的特征标相同,而变量名是无关紧要的。C++允许定义相同名称的函数,条件是特征值不同。

例如:

inline void print(const char * str, int value) {cout <<"string "<< str << value << endl;};
inline void print(double b, int value) {cout << "double "<< b << value << endl;};
inline void print(long b, int value) {cout << "long " <<b << value << endl;};
inline void print(int b, int value) {cout <<"int " << b << value << endl;};
inline void print(const char * str) {cout <<  str  << endl;};

int main(int argnum,char *args[]) {
    print(12,22);
    print(12.0,22);
    print(long(12),22);
    print("12");
    print("12",12);
    # print(unsigned(12),22); // 报错
    return 0;
}

print(unsigned(12),22) 报错原因:

当没有匹配函数时,原型不会自动停止使用其中的某个函数,因为C++会尝试使用强制类型转换去强制匹配。如果上面的原型只有一个:

inline void print(double b, int value) {cout << "double "<< b << value << endl;};

函数会强制将unsigned(12)转换成double类型再进行匹配。但是这里有强制转换后能够匹配的函数有三个,这种情况下,C++将拒绝这种函数调用,并将其看做错误;

一些看起来特征不同的函数也可能不能共存:

double cule(int x);
double cule(int & x);

这里的参数类型不同,但是从编译器角度讲,同一变量能够匹配两个函数,编译器不能分辨使用哪个函数。

匹配函数时,区分const 与非const变量

inline void print(const char * str, int value) {cout <<"const string "<< str << value << endl;};
inline void print(char * str, int value) {cout <<"string "<< str << value << endl;};


int main(int argnum,char *args[]) {
    print("12",12);
    char a[5] = "asd";
    print(a,12);
    return 0;
}

print() 函数有两个原型,一个用于const指针,另一个用于常规指针。编译器将根据实参是否为const来决定是否匹配。

五 函数模板:

函数模板是通用的函数描述,也就是说,它们使用泛型定义函数。

template <typename T>
void swap1(T &a,T &b);

int main(int argnum,char *args[]) {
    int a = 12;
    int b = 13;
    swap1(a,b);
    cout << a;
    return 0;
}

template <typename T>
void swap1(T &a,T &b){
    T tmp;
    tmp = a;
    a = b;
    b = tmp;
}
显式具体化:

在使用函数模板情况下,为某种特定类型的参数单独定义函数。

#include <iostream>
#include <string>
using namespace std;
struct job{
    std::string name;
    int age;
};
template <typename T>
void swap1(T &a,T &b);

template <> void swap1<job>(job &a,job &b);

int main(int argnum,char *args[]) {
    int a = 12;
    int b = 13;
    swap1(a,b);
    cout << a << endl;

    job j1{"lin",12};
    job j2{"lin2",20};

    swap1(j1,j2);
    cout << j1.name << "  " << j1.age << endl;
    return 0;
}

template <typename T>
void swap1(T &a,T &b){
    T tmp;
    tmp = a;
    a = b;
    b = tmp;
    cout << "use T" << endl;
}

template <> void swap1<job>(job &a,job &b){
    std::string tmp;
    tmp = a.name;
    a.name = b.name;
    b.name = tmp;
    cout << "use job" << endl;
}

关键字decltype :
#include <iostream>
#include <string>

using namespace std;

template <typename T1,typename T2>
auto Add(T1 x,T2 y) -> decltype(x + y);

int main(int argnum,char *args[]) {
    int a = 12;
    double b =22.5;
    cout << Add(a,b)  << endl;
    return 0;
}

template <typename T1,typename T2>
auto Add(T1 x,T2 y) -> decltype(x + y){
    decltype(x + y) result = x + y;
    return result;
}

decltype 解决了多个类型时无法定义 reslut类型的问题。并且与auto连用,可以定义返回值类型。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值