函数与程序结构
- 函数的声明与定义
- 函数的声明
- 函数的定义
- 函数重载
- 内联函数
- 递归函数
- 构造函数
- lambda 函数
- 函数的参数
- 形参和实参
- 值传递和引用传递
- 默认参数
- 函数的返回
- 返回多个值
- 返回引用
- 返回指针
- 返回对象
- 头文件
- 内部函数和外部函数
- 内部函数
- 外部函数
函数的声明与定义
函数的声明
- 在使用函数之前,需要提供函数的声明。声明告诉编译器有一个函数存在,但不提供具体的实现
- 通常在头文件(.h)中进行函数声明,以便在多个文件中共享函数接口
- 函数声明包括函数的返回类型、函数名、参数列表(参数类型和参数名),但不包括函数体
// 函数声明 int add(int a, int b);
函数的定义
就是cpp里的函数的具体实现
// 函数定义
int add(int a, int b) {return a + b;
}
函数重载
C++允许在同一作用域中声明多个具有相同名称但参数列表不同的函数
// 函数重载
int add(int a, int b);
double add(double a, double b);
内联函数
- 什么是内联函数?——参考文章
- 使用场景:
内联函数通常用于需要频繁调用、函数体较小且性能敏感的情况。它是一种编译器的优化手段,可以提高程序的执行效率。内联函数的使用场景包括但不限于:
小型函数体: 内联函数适用于函数体较小的情况,因为内联函数会将函数体的代码插入到每次调用的地方,如果函数体较大,内联可能会导致代码膨胀,影响性能。
频繁调用的函数: 内联函数适用于频繁调用的函数,因为函数调用本身会有一些开销,内联可以减少这种开销。
性能敏感的代码: 内联函数适用于对性能要求较高的代码段,因为它可以减少函数调用的开销,提高执行速度。 - 内联函数是在编译时期处理的,而不是在预处理时期。在编译时,编译器会根据函数的声明和定义,在每次调用的地方插入函数体的代码,而不是像普通函数一样生成一个独立的函数调用。这样可以减少函数调用的开销,但也会增加代码的体积。因此,内联函数的使用需要谨慎,最好在性能分析的基础上进行决策。
递归函数
递归函数是调用自身的函数。递归函数需要有一个终止条件,否则将无限循环
// 递归函数
int factorial(int n) {if (n <= 1) {return 1;}return n * factorial(n - 1);
}
构造函数
- 语法:
类名(){}
- 构造函数,没有返回值也不写void
- 函数名称与类名相同
- 构造函数可以有参数,因此可以发生重载
- 程序在调用对象时候会自动调用构造,无须手动调用,而且只会调用一次
lambda 函数
[capture](parameters) -> return_type {// 函数体
}
- capture:捕获列表,用于在 lambda 函数中引用外部变量。捕获列表可以为空,也可以包含变量名、变量列表,或者通过引用捕获。
parameters:参数列表,与普通函数的参数列表相似,但可以为空。
-> return_type:返回类型声明,可以省略,编译器会自动推导返回类型。
{}:函数体
#include <iostream>
int main() {// Lambda 表达式,将两个数相加auto add = [](int a, int b) -> int { //auto 用于自动推导变量的类型return a + b;};// 使用 Lambda 函数int result = add(3, 4);std::cout << "The sum is: " << result << std::endl;return 0;
}
函数的参数
形参和实参
- 形参
- 形参是函数定义中声明的变量,用于接收调用该函数时传递的实参
- 形参在函数定义的括号内声明,它们是函数体内的局部变量,只在函数内部可见
- 形参的作用是充当函数内部的占位符,用于处理传递给函数的实际数据
void exampleFunction(int parameter1, float parameter2) {// function body }
- 实参
- 实参是函数调用时传递给函数的具体数值或变量
- 实参与形参一一对应,按顺序传递给函数。实参的值被赋给对应位置的形参
- 实参可以是常量、变量、表达式等
int main() {int a = 10;float b = 3.14;// 调用函数并传递实参exampleFunction(a, b);return 0; }
值传递和引用传递
- 值传递是指将实参的值复制给形参,在函数内部对形参的修改不影响实参
- 引用传递是通过传递实参的引用,使函数能够直接操作实参的值
#include <stdio.h> void byReference(int& x) {x = x * 2; } void byValue(int x) {x = x * 2; } int main(int argc, char** argv) {int a=2,b=2;byValue(a);byReference(b);printf("a=%d\n", a);printf("b=%d\n", b); } //结果为a=2;b=4
默认参数
默认参数是在函数声明中为形参设置默认值,如果调用函数时没有提供对应实参,将使用默认值
// 函数声明,其中 b 的默认值为 10
void exampleFunction(int a, int b = 10);
// 函数定义
void exampleFunction(int a, int b) {// 函数体
}
函数的返回
返回多个值
可以使用结构体、数组或类等方式实现函数返回多个值的效果
struct Point {int x, y;
};
Point getCoordinates() {Point p;p.x = 10;p.y = 20;return p;
}
返回引用
#include <stdio.h>
int x = 5;
int& getVariable() {return x;
}
int main(int argc, char** argv)
{getVariable() = 10;printf("x的值为:%d\n", x); // x 现在的值是 10return 0;
}
返回指针
函数可以返回指针,通常用于返回动态分配的内存
int* createInt() { //返回一个指向整数的指针 (int*)int* ptr = new int; //使用 new 运算符在堆上动态分配了一个新的整数。这个新分配的内存的地址被存储在指针变量 ptr 中*ptr = 42; //设置了这个内存位置的值return ptr;//return *ptr;如果这样写就是返回int型
}
返回对象
通常用于实现链式调用(也叫流式接口)
在 C++ 中,& 符号用于声明引用
#include <iostream>
struct MathOperations {int value;MathOperations& add(int x) {value += x;return *this;}MathOperations& multiply(int x) {value *= x;return *this;}
};
int main() {MathOperations result{5}; //value 成员初始化为 5result.add(3).multiply(2);std::cout << "Result: " << result.value << std::endl; // 输出:Result: 16return 0;
}
- return this与return *this区别
参考文章
return *this返回的是当前对象的克隆或者本身(若返回类型为A, 则是克隆, 若返回类型为A&, 则是本身 )。return this返回当前对象的地址(指向当前对象的指针)
头文件
- 头文件保护
头文件保护(也称为 include guard 或防卫式声明)是一种防止头文件被多次包含的机制。通过#ifndef、#define、#endif 来实现// 头文件保护示例 #ifndef EXAMPLE_H #define EXAMPLE_H// 头文件内容 #endif
- 内联函数
通常直接放在头文件中,以便在编译时进行函数体的替换,提高性能// 内联函数示例 #ifndef EXAMPLE_H #define EXAMPLE_Hinline int add(int a, int b) {return a + b; } #endif
内部函数和外部函数
内部函数
- 内部函数是在另一个函数内部定义的函数
内部函数的作用域限定在外部函数中,无法在外部函数以外的地方调用
内部函数通常用于封装和隐藏实现细节
void outerFunction() {// 内部函数void innerFunction() {// 内部函数的实现}// 调用内部函数innerFunction();
}
外部函数
- 默认情况下,函数(除了静态函数和内部函数)具有外部链接性,可以在其他文件中调用
- 外部函数的声明通常放在头文件中,以便在多文件项目中共享函数接口。