函数

基本概念

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/*返回类型 函数名(参数列表){
函数体;
}
*/
//定义函数
long long power(int x, int n){
long long res = 1;
while(n--){
res *= x;
}
return res;
}
//调用函数
power(2, 3);
  • 返回类型

    返回类型代表函数运算后返回的结果类型

  • 函数名

    函数的标识符

  • 参数列表

    调用函数时需要的数据以及类型

  • 函数体

    在函数内部通过传入的数据来得出结果的计算过程

在调用函数时输入的参数称为实际参数(即实参),函数定义时的参数成为形式参数(即形参)

关键字==return==作用:

  • 返回值
  • 结束函数

函数类型为void时没有返回值,代表空,正常执行时不需要return

参数的引用

1
2
3
4
5
6
void swap(int &x, int &y){
int temp = x;
x = y;
y = temp;
}
swap(a, b);

若不加&符号,不会对实参进行改变.因此只有加上引用符号后才能对传递进来的实参进行修改

特殊类型

对于vector,string这类复合数据类型,如果按数值来传递,相当于新建了一个同样大小的数据,同时将形参的数据赋值给函数的形参,性能低效

因此尽可能用引用来传递非基础类型(因为指向同一个内存并不会发生数据的拷贝)

同样如果传递数组不带引用符号的话,数组会发生隐式转换变成指针类型

(typeid函数可获取数据类型)

1
2
3
4
void forward(auto &arr);//使用auto是比较危险的行为但可做题小范围使用
void forward(int (&arr)[3]); //要声明具体长度
template<size_t N>//模板,C++高级特性
void forward(int (&arr)[N]);

main函数

Lambda 函数

Lambda 函数(也称为匿名函数或 lambda 表达式)是 C++11 及以后版本中引入的一种方便的语法结构,它允许你在不定义传统函数的情况下创建函数对象。Lambda 函数通常用于简短的、一次性的函数,或者作为参数传递给算法,如 std::sortstd::for_each 等。

Lambda 函数的基本语法如下:

1
[capture](parameters) -> return_type { function_body }

其中各个部分的含义如下:

  1. 捕获子句(capture clause) [capture]
    • 指定了 lambda 函数从封闭作用域(通常是包含它的函数)中捕获哪些变量。
    • 可以捕获变量的值 [=] 或引用 [&],也可以通过名称 [a, &b] 指定特定的变量捕获。
    • 如果不需要捕获任何变量,可以省略捕获子句。
  2. 参数列表(parameter list) (parameters)
    • 指定了 lambda 函数的参数,类似于传统函数的参数列表。
    • 如果没有参数,可以省略参数列表,或者使用空括号 ()
  3. 返回类型(return type) -> return_type
    • 指定了 lambda 函数的返回类型。
    • 如果 lambda 函数的返回类型可以由编译器推断,可以省略返回类型。
  4. 函数体(function body) { function_body }
    • 包含了 lambda 函数的执行代码,类似于传统函数的函数体。

以下是一些 lambda 函数的例子:

例子 1:无参数,无返回值

1
[]() { std::cout << "Hello, World!" << std::endl; };

例子 2:有参数,无返回值

1
[](int x, int y) { std::cout << "Sum: " << x + y << std::endl; };

例子 3:有参数,有返回值

1
[](int x, int y) -> int { return x + y; };

例子 4:捕获外部变量

1
2
int a = 10;
auto lambda = [a]() { std::cout << "a: " << a << std::endl; };

例子 5:捕获外部变量并修改

1
2
3
int a = 10;
auto lambda = [&a]() { a = 20; };
lambda(); // 修改外部变量 a 的值

Lambda 函数可以被存储在变量中,作为参数传递给函数,或者直接在需要的地方使用。它们是现代 C++ 编程中非常灵活和强大的工具。

匿名函数

sort

void sort(Iterator first, Iterator last, Function comparer);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
bool comparer(int a, int b){
//a是否在b前面,a是否小于b
if(a % 2 != b % 2){
return a % 2 == 1;
}
return a < b;
}
int main(){
int arr[] = {5, 8, 4, 3, 2, 9, 7, 1, 6};
sort(arr, arr + 9, comparer);
}
//或者直接写
sort(arr , arr + 9, [](int a, int b) -> bool{
if(a % 2 != b % 2){
return a % 2 == 1;
}
return a < b;
});

find_if

作用:查找范围内第一个满足条件的元素

返回值为迭代器或者地址

Iterator find_if(Iterator first, Iterator last, Function matcher);

1
2
3
4
5
6
7
8
bool matcher(int x) {
return x > target;
}
vector<int> vec = {5, 8, 4, 3, 2, 100, 7, 1, 6};
int target = 10;
find_if(vec.begin(), vec.end(), [target](int x) {
return x > target;
});

[]的意义是捕获,代表捕获一些变量使得可以在函数内正常访问

[]捕获

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
int x, y ,z;
//值捕获
[x]() {
x;
x = 1;//错误的写法,因为不能在函数内修改值的量
}
//引用捕获
//如果想修改x的值,需要加上引用,写作 [&x]
[=]() {
//写等于号代表捕获了x, y, z
x, y, z;
}
[&]() {
//只写引用符号代表引用捕获了x, y, z
x = y = z = 1;
}
//也可以混合使用
//初始化捕获
int x = 5;
[x, init = x * x]() mutable {
x, init;
//只在匿名函数内生效
//加上mutable的修改 只在函数内部生效 和引用捕获不同
}

判断依据:

  • 如果想在函数内改变变量 使用引用捕获
  • vector string 等建议使用引用捕获

==mutable==可改变的,加上mutable关键字之后可以改变捕获的值(只在函数内部生效,和引用捕获不同) 加在括号和花括号之间

1
auto swap = [](int &a, int &b) {  };//花括号内写函数具体内容  

匿名函数的递归调用

1
2
3
4
5
auto fib = [](auto& self, int x) {
if(x <= 2) return 1;
return self(self, x - 1) + self(self, x - 2);
};//self代表函数自身
cout << fib(fib, 10) << endl;

递归

基础概念

递归,即调用函数自身。本质上是将问题拆解成更小规模的相同问题。

简单优化思路(==记忆化搜索==):如果有重复计算,将结果保存下来

递归方法:

  • 确定问题
  • 解决基准问题
  • 拆解问题

示例

斐波那契数列(Fibonacci)

1
2
3
4
int fib(int n){
if(n <= 2) return 1;
return fib(n-1) + fib(n-2);
}

当出现重复问题时数据会成指数型增长,子问题会被重复计算多次.

可以在计算时将计算过的保存下来,并在计算时再判断是否计算过,用来优化性能

1
2
3
4
5
6
7
8
vector<int> saved(n,-1);
int fib(int n){
if(n <= 2) return 1;
if(saved[n] == -1){
saved[n] = fib(n-1) + fib(n-2);
}
return saved[n];
}

汉诺塔(honai)

1
2
3
4
5
6
7
8
9
void hanoi(int n, char F, char A, char T){
if(n == 1){
printf("move %d from %c to %c\n", n, F, T);
return;
}
hanoi(n - 1, F, T, A);
printf("move %d from %c to %c\n", n, F, T);
hanoi(n - 1, A, F, T);
}