前端学C++

105 阅读2分钟

这是我参与11月更文挑战的第6天,活动详情查看:2021最后一次更文挑战

函数

看了看C++ Premier Plus在函数上花的篇幅,想在两篇内总结函数的知识点似乎不太现实。。。

函数声明与定义

多数语言的函数声明与使用都很相似,C++也不例外,只是作为强类型语言,C++要求明确地声明函数返回类型与参数列表及类型:

typeName functionName(parameterList){
    // ...
}
int bigger(int a, int b) { 
    if (a > b ) 
        return a; 
    else 
        return b; 
}

一个C++中函数使用地特性是,需要把函数在文件头部先声明一遍(虽然这种做法叫做prototype,但显然翻译为声明比原型更为合适),如下:

double cube(double x); // function prototype ... 
int main() { 
    ... 
    double q = cube(1.2); // function call 
    ... 
} 
double cube(double x) // function definition 
{ 
    return x * x * x; 
}

诶,这个做法不就是JS中常讲地提升吗,变量和函数的定义在编译过程中自动被提升到文件的头部,只是C++中我们需要自己去做这件事。尽管讲JS提升的文章看过不知道多少篇,但从来没一篇说为什么要提升的,而C++ Premier Plus好心地告诉了我原因:尽管对于程序员来说这种提升是个废操作,但对于编译器而言,了解一个函数地的返回值、参数列表有助于其了解函数的返回值要放在哪里(寄存器or内存),进而知道去哪里取值。

那么问题来了,编译器不能自己去找函数定义吗?答案是,C++不想这么做,除了出现在文件下方,函数定义可能在引入的其他文件中,但根本原因是,C++不愿意浪费时间干这种降低编译器效率的事,这是C++的哲学。

函数传值与递归

C++函数的参数实际的行为是:

  • 根据函数的形参名称,创造一个同名变量,把传入的值赋给该变量
  • 函数内部逻辑执行
  • 函数结束执行返回,该变量被释放(对内存地址而言是释放,也可以认为这个变量就被销毁了) 这个说法和JS中的函数作用域是相似的。事实上,最直白易懂的函数传值讲解就是搞明白递归函数了:
void countdown(int n); 
int main() { 
    countdown(4); 
    return 0; 
} 
void countdown(int n) { 
    using namespace std; 
    cout << "Counting down ... " << n << " (n at " << &n << ")" << endl;
    if (n > 0) 
        countdown(n-1); // 递归
    cout << n << ": end!"; << " (n at " << &n << ")" << endl;
}
//输出
Counting down ... 4 (n at 0012FE0C) 
Counting down ... 3 (n at 0012FD34) 
Counting down ... 2 (n at 0012FC5C) 
Counting down ... 1 (n at 0012FB84) 
Counting down ... 0 (n at 0012FAAC) 
0: end! (n at 0012FAAC) 
1: end! (n at 0012FB84) 
2: end! (n at 0012FC5C) 
3: end! (n at 0012FD34) 
4: end! (n at 0012FE0C)