16人参与 • 2025-07-18 • C/C++
lambda 表达式本质是⼀个匿名函数对象,跟普通函数不同的是他可以定义在函数内部。
lambda 表达式语法使⽤层⽽⾔没有类型,所以我们⼀般是⽤auto或者模板参数定义的对象去接收 lambda 对象
lambda表达式的格式: [capture-list] (parameters)-> return type {function boby }
auto add1 = [](int x, int y)->int {return x + y; }; cout << add1(1, 2) << endl; // 1、捕捉为空也不能省略 // 2、参数为空可以省略 // 3、返回值可以省略,可以通过返回对象⾃动推导 // 4、函数题不能省略 auto func1 = [] { cout << "hello bit" << endl; return 0; };
auto func1 = [a, &b] { // 值捕捉的变量不能修改,引⽤捕捉的变量可以修改 //a++; b++; int ret = a + b; return ret; }; auto func2 = [=] { int ret = a + b + c; return ret; }; auto func6 = [] { int ret = x + m; return ret; }; auto func4 = [&, a, b] { //a++; //b++; c++; d++; return a + b + c + d; }; auto func5 = [=, &a, &b] { a++; b++; /*c++; d++;*/ return a + b + c + d; }; auto func7 = [=]()mutable { a++; b++; c++; };
但如果lambda是写在类里面的,那么lambda是不能够捕获私有成员变量的,也是不能直接使用的,如果想使用需要捕获this指针
class a { public: void f() { auto add1 = [this](int a,int b){return a + b + _a1 + _a2}; } private: int _a1 = 1; int _a2 = 2; };
在学习 lambda 表达式之前,可调用对象只有函数指针和仿函数对象,函数指针的类型定义起来比较麻烦,仿函数要定义⼀个类,相对会比较麻烦。使用 lambda 去定义可调用对象,既简单又方便。
sort(v.begin(), v.end(), [](const goods& g1, const goods& g2) { return g1._price < g2._price; });
因为sort
会将迭代器区间传给后面的对象,所以需要两个参数。
std::function
是⼀个类模板,也是⼀个包装器。 std::function
的实例对象可以包装存储其他的可以调⽤对象,包括函数指针、仿函数、 lambda 、 bind 表达式等,存储的可调用对象被称为 std::function
的⽬标。若 std::function
不含⽬标,则称它为空。调⽤空std::function
的⽬标导致抛出 std::bad_function_call
异常
int f(int a, int b) { return a + b; } struct fun { public: int operator()(int a,int b) { return (a + b) * 10; } }; int main() { auto lf = [](int a, int b) {return (a + b) * 30; }; function<int(int, int)>f1(f); //function<int(int, int)>f2(fun());编译器会将其解释为函数声明而不是变量定义,这被称为"最令人烦恼的解析" function<int(int, int)>f2 = fun(); function<int(int, int)>f3(lf); vector<function<int(int, int)>>vf = { f,fun(),lf }; cout << f1(2, 3) << endl; cout << f2(1, 2) << endl; cout << lf(4, 5) << endl; for (auto p : vf) { cout << p(1, 2) << endl; } return 0; }
函数指针、仿函数、 lambda 等可调⽤对象的类型各不相同, std::function
的优势就是统⼀类型,对他们都可以进⾏包装,这样在很多地⽅就⽅便声明可调⽤对象的类型。
可以把function当做把可调用对象进行统一为一个类型,这样就可以将其储存到容器中。
如果包的是成员函数的话需要注意,由于类的成员函数的第一个参数是默认为this指针,所以function实例化的类型需要有类的对象的地址或者是对象,即使传的是对象,对象会使用.*
操作符对this指针进行调用。
class plus { public: plus(int n = 10) :_n(n) {} static int plusi(int a, int b) { return a + b; } double plusd(double a, double b) { return (a + b) * _n; } private: int _n; }; int main() { // 包装静态成员函数 // 成员函数要指定类域并且前⾯加&才能获取地址 //静态成员函数是可以不加& function<int(int, int)> f4 = &plus::plusi; cout << f4(1, 1) << endl; // 包装普通成员函数 // 普通成员函数还有⼀个隐含的this指针参数,所以绑定时传对象或者对象的指针过去都可以 function<double(plus*, double, double)> f5 = &plus::plusd; plus pd; cout << f5(&pd, 1.1, 1.1) << endl; function<double(plus, double, double)> f6 = &plus::plusd; cout << f6(pd, 1.1, 1.1) << endl; cout << f6(pd, 1.1, 1.1) << endl; function<double(plus&&, double, double)> f7 = &plus::plusd; cout << f7(move(pd), 1.1, 1.1) << endl; cout << f7(plus(), 1.1, 1.1) << endl; }
<functional>
这个头⽂件中。auto newcallable = bind(callable,arg_list)
; 其中newcallable本⾝是⼀个可调⽤对象,arg_list是⼀个逗号分隔的参数列表,对应给定的callable的参数。当我们调⽤newcallable时,newcallable会调用callable,并传给它arg_list中的参数。placeholders
的⼀个命名空间中。using placeholders::_1; using placeholders::_2; using placeholders::_3; int sub(int a, int b) { return (a - b) * 10; } int main() { auto sub1 = bind(sub, _1, _2); cout << sub1(10, 5) << endl; // bind 本质返回的⼀个仿函数对象 // 调整参数顺序(不常⽤) // _1代表第⼀个实参 // _2代表第⼆个实参 // ... auto sub2 = bind(sub, _2, _1); cout << sub2(10, 5) << endl; // 调整参数个数 (常⽤) auto sub3 = bind(sub, 100, _1); cout << sub3(5) << endl; auto sub4 = bind(sub, _1, 100); cout << sub4(5) << endl; // 分别绑死第123个参数 auto sub5 = bind(subx, 100, _1, _2); cout << sub5(5, 1) << endl; cout << bind(subx, 100, _1, _2)(5, 1) << endl; auto sub6 = bind(subx, _1, 100, _2); cout << sub6(5, 1) << endl; auto sub7 = bind(subx, _1, _2, 100); cout << sub7(5, 1) << endl; return 0; }
bind对于我们之前用function来包装成员函数时第一个参数必须传对象的情况做出了改变,可以用bind来绑定第一个参数,这样在后续调用该可调用对象的时候就可以不用传对象了
// 成员函数对象进⾏绑死,就不需要每次都传递了 function<double(plus&&, double, double)> f6 = &plus::plusd; plus pd; cout << pd.plusd(1.1, 1.1) << endl; cout << f6(move(pd), 1.1, 1.1) << endl; cout << f6(plus(), 1.1, 1.1) << endl; auto f = bind(&plus::plusd, &pd, _1, _2); function<double(double, double)> f2 = bind(&plus::plusd, &pd, _1, _2); cout << f(1.1,1.1) << endl; cout << f2(1.1, 1.1) << endl;
到此这篇关于c++11之lambda表达式与包装器的文章就介绍到这了,更多相关c++ lambda表达式内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论