🐶博主主页:@ᰔᩚ. 一怀明月ꦿ
❤️🔥专栏系列:线性代数,C初学者入门训练,题解C,C的使用文章,「初学」C++
🔥座右铭:“不要等到什么都没有了,才下定决心去做”
🚀🚀🚀大家觉不错的话,就恳求大家点点关注,点点小爱心,指点指点🚀🚀🚀
c++11中的lambda表达式
lambda表达式的基本格式
[capture list] (parameters) -> return_type { // 函数体 }
* capture-list:用于捕获外部变量,可以省略。捕获方式有三种:
* [&]:以引用方式捕获所有外部变量。
* [=]:以值的方式捕获所有外部变量。
* [var1, var2, ...]:指定需要捕获的外部变量列表,可以使用 & 或 = 来指定捕获方式。
* parameter-list:函数参数列表,类似于普通函数的参数列表,可以省略。
* return-type:返回类型,可以省略,编译器可以自动推断。
* body:Lambda 函数体,类似于普通函数体,包含了执行的语句。
下面是一个简单的示例,展示了如何在 C++11 中使用 Lambda 表达式:
不使用捕捉列表 capture-list
#include <iostream> int main() { // Lambda 表达式示例:计算两个数的和 //参数列表有两个整数 auto add = [](int a, int b) -> int { return a + b; }; // 调用 Lambda 表达式 int result = add(3, 4); std::cout << "Result of add function: " << result << std::endl; // Lambda 表达式示例:打印 Hello World //参数列表为空 auto printHello = []() { std::cout << "Hello, World!" << std::endl; }; // 调用 Lambda 表达式 printHello(); return 0; }
使用捕捉列表 capture-list
int main() { int x=119,y=120; cout<<"x="<<x<<":"<<"y="<<y<<endl; //参数列表为空,调用时不需要传递参数 auto f1=[&x,&y]() { int temp; temp=x; x=y; y=temp; };//[]就是捕捉列表,可以捕捉lambda表达式所在函数(这里是main函数)里的变量,提供自己使用,这里采用的是引用捕捉x,y,因为我们要在lambda的函数体里修改x,y,如果不需要修改x,y的值时,可以采用值捕捉[x,y](){} f1(); cout<<"x="<<x<<":"<<"y="<<y<<endl; return 0; }
使用捕捉列表 capture-list的其他用法
int main() { int x = 1,y = 2,z = 3; //以值的方式捕捉所有的变量 auto f1=[=](){ cout<<x<<y<<z<<endl; };//[=]是捕捉所有变量的意思 f1(); //以引用的方式捕捉所有的变量 auto f2=[&](){ cout<<x<<y<<z<<endl; };//[&]是捕捉所有变量的意思 f2(); //以值的方式捕捉所有的变量,指定x,y以引用捕捉 auto f3=[=,&x,&y](){ cout<<x<<y<<z<<endl; }; f3(); return 0; }
lambda的底层其实是一个仿函数
包装器
function
function
是 C++ 标准库中的一个模板类,用于封装可调用对象,包括函数指针、函数对象、lambda 表达式等等,使用时需要functional头文件。
function
的定义如下:template<class R, class... Args> class function<R(Args...)>;
其中
R
是返回类型,Args
是参数类型。通过这个定义,你可以创建一个function
对象,它可以接受参数为Args
类型,返回类型为R
类型的可调用对象。事例1)
void swap_func(int& r1,int& r2) { int temp; temp=r1; r1=r2; r2=temp; } struct swap_2 { void operator()(int& r1,int& r2) { int temp; temp=r1; r1=r2; r2=temp; } }; int main() { int x=119; int y=120; auto lambdaswap=[](int& r1,int& r2) { int temp; temp=r1; r1=r2; r2=temp; }; //包装器指向swap_func函数 function<void(int&,int&)> f1=swap_func; f1(x,y); cout<<"x:"<<x<<" y:"<<y<<endl; //包装器指向仿函数 function<void(int&,int&)> f2=swap_2();//swap_2() 是一个函数调用操作符 operator() 被重载的类 swap_2 的匿名对象。在 C++ 中,类的对象也可以被当作函数使用,如果该类定义了一个函数调用操作符 operator(),就可以像调用函数一样使用这个对象。在这种情况下,swap_2() 返回的匿名对象会被当作函数使用,具体来说,它会被当作一个函数对象使用。 f2(x,y); cout<<"x:"<<x<<" y:"<<y<<endl; //包装器指向lambda表达式 function<void(int&,int&)> f3=lambdaswap; f3(x,y); cout<<"x:"<<x<<" y:"<<y<<endl; return 0; }
事例2)
class Test { public: int add(int x,int y) { return x+y; } static int add_s(int x,int y){ return x+y; } }; int main() { //包装器指向静态成员函数 //需要加域名 function<int(int,int)> f1=Test::add_s; int sum=f1(1,2); cout<<sum<<endl; //包装器指向普通成员函数 //1.需要加域名 //2.需要取地址 //3.function需要多加一个类的指针(因为成员函数的参数列表中,隐含一个this指针) function<int(Test*,int,int)> f2=&Test::add; Test t1; int num=f2(&t1,1,2); cout<<num<<endl; }
function封装可调用对象,包括函数指针、函数对象、lambda 表达式时,一定保证参数类型是相同的
bind
在C++中,
std::bind
是一个函数模板,用于创建一个可调用对象,该对象可以绑定到函数、成员函数、函数对象或者其他可调用对象,并且可以指定部分或全部参数的值。std::bind
允许你在调用时提供缺少的参数,或者在调用时提供额外的参数。
bind
的基本语法如下:template< class F, class... Args > /*unspecified*/ bind( F&& f, Args&&... args );
其中
F
是可调用对象的类型,args
是可调用对象的参数。bind
返回一个可调用对象,该对象可以通过调用其operator()
来调用绑定的函数或函数对象,并传递给它们参数。事例
class Test { public: int add(int x,int y) { return x+y; } static int add_s(int x,int y){ return x+y; } }; int sub(int x,int y) { return x-y; } int main() { //调整参数顺序 function<int(int,int)> f1=bind(sub,placeholders::_2,placeholders::_1); //bind第一个参数是函数名,placeholders::_2,placeholders::_1可用来改变参入参数的顺序的 int num=f1(2,0);//顺序变为sub(0,2) cout<<num<<endl; //调整参数个数 function<int(int)> f2=bind(sub,100,placeholders::_1); //我们也可以在绑定的时候,提前加入指定的参数,例如这里的100,这样我们调用sub时就只需要传一个参数 int num1=f2(1); cout<<num1<<endl; //调整参数个数 function<int(int,int)>f3=bind(&Test::add,Test(),placeholders::_1,placeholders::_2); //绑定的Test是一个自定义类型的普通成员函数,传函数名时需要加域名和&,这个Test()是Test的匿名对象,需要传递给this指针 int num2=f3(2,3); cout<<num2<<endl; return 0; }
🌸🌸🌸如果大家还有不懂或者建议都可以发在评论区,我们共同探讨,共同学习,共同进步。谢谢大家! 🌸🌸🌸