第07章 函数

<c++ primer plus>第六版

7 函数

7.1 复习函数的基本知识

没有返回值的函数:

void FunctionName(parameterList)
{
    statments
    return; //optional
}

有返回值的函数

typeName FunctionName(parameterList)
{
    statments
    return value; //value的数据类型为TypeName.
}

7.2 函数参数和按值传递

7.3 函数和数组

将数组作为函数的参数

给函数传递常规变量时, 函数将使用变量的拷贝, 但传递数组时, 函数将使用原数组(函数得到的是数组地址).
优点: 节省复制整个数组所需的时间和内存.
缺点: 增加了破坏原始数据的风险(可以通过const限定符规避).

注意, 需要同时传递元素个数, 因为函数得到的是数组的地址, 对这个地址使用sizeof, 得到的是地址的长度, 而不是数组长度.


参数传递本质上是赋值, 将一块内存的数据复制到另一块内存上.
c/c++禁在函数调用时传递数组内容, 而是强制传递数组指针, 但对struct和object没有限制.

基本类型: char, int, float等.
聚合类型: 数组, 结构体, 类. 它们由基本类型组合而成. 也称为复杂类型/构造类型.

可以使用引用传递聚合类型数据.

#include<iostream>
const int ArraySize=8;

//函数第一个参数是数组, 也可以写做
//int sum_arr(int arr[], int n);
//在C++中, 当且仅当用于函数原型或函数头中时, int * arr和int arr[]的含义相同
int sum_arr(int * arr, int n);

int main()
{
    using namespace std;
    int cookies[ArraySize] = {1,2,4,8,16,32,64,128};

    int sum = sum_arr(cookies, ArraySize); //直接传递数组名, 实际传递的是第0元素的地址&cookies[0]
    cout << "Total count: " << sum << endl;

    return 0;
}

int sum_arr(int arr[], int n) //函数得到的是数组地址, 所以函数内部可以修改数组内容.
{
    int total = 0;
    for (int i=0; i<n; i++)
    {
        total += arr[i];
    }
    return total;
}

//使用const修饰传入的数组, 可以防止函数无意中修改数组内容.
void show_array(const double ar[], int n);

7.4 函数和二维数组

7.10 函数指针

函数的地址是存储其机器语言代码的内存的开始地址.
使用函数地址就可以用来传递函数.
函数名即函数的地址, 如果函数名后加了括号, 就是函数调用.

double pam(int);   //函数原型, 返回值类型为double
double (*pf)(int); //pf是一个指针, 指向函数, 该函数返回值为double
pf = pam;          //pf现在指向pam()函数

double x = pam(4);   //使用函数名调用函数.
double y = (*pf)(5); //使用指针调用函数.
double z = pf(5);    //仍然是使用指针调用函数, 但无法看出是通过指针调用的.

注意 double *pf(int), 表示pf()是一个函数, 它的返回值是指针, 该指针指向double类型.

7.10.4 使用typedef进行简化

typedef double real; //给double取个别名就real.

typedef const double *(p_fun)(const double *, int); //p_fun就成为一个类型名
p_fun p1 = f1; //p1指向f1()function

===================================

函数定义分成两部分: 函数原型, 函数体:

//函数原型, 这时参数变量名可以省略, 只保留变量类型.
返回值类型 函数名(int, int);


//实际函数的定义
返回值类型 函数名(参数声明){
    函数体;
    return 表达式;
}

//内联函数(inline function)
定义方法:在函数定义处增加inline关键字

inline void swap(int *a, int *b){
    语句;
}

作用: 在编译时, 将对该函数的调用改为函数体, 消除函数调用的开销. 一般将短小的函数声明为inline function.
注意: inline关键字添加在函数定义的地方, 不能添加在函数声明的地方(会被忽略).

//函数重载(Function Overloading)
多个函数可以拥有相同的名字, 只要它们的参数列表不同就可以;
参数列表不同包括: 参数类型不同, 参数个数不同, 参数顺序不同;
函数重载原理: 编译时要根据参数列表对函数进行重命名, void SWAP(int a, int b)会重命名为_SWAP_int_int, 函数调用时根据参数匹配编译后的函数;

posted @ 2022-07-10 11:07  编程驴子  阅读(25)  评论(0编辑  收藏  举报