函数指针

函数的本质是一个指针,在c++中我们可以将函数赋值给一个变量,但是在实际过程中,这个变量得到的是函数的地址,也就是函数指针,在cpu中我们每次编译函数都是由cpu直接编译,存在于二进制文件中。

则函数变量的类型语法为:返回值类型(*变量名)(函数参数类型);

示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <iostream>

void HelloWorld()
{
std::cout << "HelloWorld" << std::endl;
}

void PrintNumber(int x)
{
std::cout << "HelloWorld" << x << std::endl;
}

int main()
{
HelloWorld();//直接调用函数
auto fun1 = HelloWorld;//将函数赋值给一个变量。此时实际上是一个指针
//auto的具体含义如下
void (*fun2)();
fun2 = HelloWorld;
//带有参数的类型
void (*fun3)(int);
fun2 = PrintNumber;
//或者直接赋值
void (*fun4)(int)=PrintNumber;
//使用时如同原函数一样使用
fun1();
fun2();
fun3(3);
fun4(4);

//一些其他定义
typedef void (*HelloWorldFun)();
HelloWorldFun fun5 = HelloWorld ;
}

由上述可以看出,在函数变量的类型定义中auto才是经常使用的类型,因为函数的参数修改后类型往往跟着一起修改,使用auto往往能更方便省力。函数指针有较为广泛的实际用途。

示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <vector>


void Print(int value)
{
std::cout << "Hello" << value << std::endl;
}

void ForEach(const std::vector<int>& values, void (*func)(int))
{
for (int value : values)
func(value);
}

int main()
{
std::vector<int> values = { 1,3,5,7,9 };
ForEach(values, Print);
}

lambda函数

lambda的本质是一种匿名函数,它就像是一种快速的一次性的函数,用完即废弃,它比起普通的函数作为符号,更倾向于将他视为一个变量。lambda就是一种不需要函数定义方式就可以定义一个函数的方法。

语法:

1
[传入方式](参数){函数体}

使用示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <vector>
#include <algorithm>

void ForEach(const std::vector<int>& values, void (*func)(int))
{
for (int value : values)
func(value);
}

int main()
{
std::vector<int> values = { 1,3,5,7,9 };
ForEach(values, [](int value) {std::cout << "Value:" << value << std::endl; });
}

如果lambda函数想要调用外部的变量就需要用到[]即他的捕获方式再[]中我们可以不填,也可以填一个或多个中间用逗号分开

使用如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>

void ForEach(const std::vector<int>& values,const std::function<void(int)>& func)
{
for (int value : values)
func(value);
}

int main()
{

std::vector<int> values = { 1,3,5,7,9 };

int a = 5;
/*
//值传递,传入所有需要的值
auto lambda = [=](int value) {std::cout << "Value1:" << value << "value2:" << a << std::endl; };
//引用传递
auto lambda = [&](int value) {std::cout << "Value1:" << value << "value2:" << a << std::endl; };
//直接指定需要的变量
auto lambda = [a](int value) {std::cout << "Value1:" << value << "value2:" << a << std::endl; };
//单独指定引用
auto lambda = [&a](int value) {std::cout << "Value1:" << value << "value2:" << a << std::endl; };
*/
//如果需要修改值传入的参数那么我们需要使用mutable
auto lambda = [=](int value) mutable {a = 6;std::cout<<"Value1:"<<value<<"value2:"<<a<<std::endl;};

ForEach(values, lambda);
}

在上述使用时,我们的lambda函数由于使用的是原始函数指针,所以在传入参数时必须使用std::function,并且在传入时必须使用const修饰。 在进行值传递后修改值需要使用mutable,不需要修改时则可以省略不写 ,并且不会修改外部的值,如果是引用传递则会修改外部值。

lambda的应用与find_if有所结合

示例:

1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>

int main ()
{
std::vector<int> values = {1,5,3,7,2};
auto it = std::find_if(values.begin(),values.end(),[](int value){return value > 3;});
cout << *it << std::endl;
}

上述代码中就会返回第一个大于3的数即5。


资料来源

youtube上the cherno的c++系列