#include<algorithm>#include<array>#include<iostream>#include<string_view>#include<string>intmain(){std::array<std::string_view,4>arr{"apple","banana","walnut","lemon"};// Ask the user what to search for.std::cout<<"search for: ";std::stringsearch{};std::cin>>search;autofound{std::find_if(arr.begin(),arr.end(),[](std::string_viewstr){// 搜索 @search 而不是 "nut".return(str.find(search)!=std::string_view::npos);// 错误: search 并不能在这里被访问})};if(found==arr.end()){std::cout<<"Not found\n";}else{std::cout<<"Found "<<*found<<'\n';}return0;}
#include<iostream>intmain(){intammo{10};autoshoot{// We don't need mutable anymore[&ammo](){// &ammo means ammo is captured by reference// Changes to ammo will affect main's ammo--ammo;std::cout<<"Pew! "<<ammo<<" shot(s) left.\n";}};shoot();std::cout<<ammo<<" shot(s) left\n";return0;}
#include<algorithm>#include<array>#include<iostream>#include<string>structCar{std::stringmake{};std::stringmodel{};};intmain(){std::array<Car,3>cars{{{"Volkswagen","Golf"},{"Toyota","Corolla"},{"Honda","Civic"}}};intcomparisons{0};std::sort(cars.begin(),cars.end(),// Capture @comparisons by reference.[&comparisons](constauto&a,constauto&b){// We captured comparisons by reference. We can modify it without "mutable".++comparisons;// Sort the cars by their make.return(a.make<b.make);});std::cout<<"Comparisons: "<<comparisons<<'\n';for(constauto&car:cars){std::cout<<car.make<<' '<<car.model<<'\n';}return0;}
可能的输出是:
1234
Comparisons: 2
Honda Civic
Toyota Corolla
Volkswagen Golf
捕获多个变量
可以通过用逗号分隔多个变量来捕获它们。这其中可以包括通过值或引用捕获的变量的组合:
123456
inthealth{33};intarmor{100};std::vector<CEnemy>enemies{};// Capture health and armor by value, and enemies by reference.[health,armor,&enemies](){};
#include<algorithm>#include<array>#include<iostream>intmain(){std::arrayareas{100,25,121,40,56};intwidth{};intheight{};std::cout<<"Enter width and height: ";std::cin>>width>>height;autofound{std::find_if(areas.begin(),areas.end(),[=](intknownArea){// will default capture width and height by valuereturn(width*height==knownArea);// because they're mentioned here})};if(found==areas.end()){std::cout<<"I don't know this area :(\n";}else{std::cout<<"Area found :)\n";}return0;}
#include<array>#include<iostream>#include<algorithm>intmain(){std::arrayareas{100,25,121,40,56};intwidth{};intheight{};std::cout<<"Enter width and height: ";std::cin>>width>>height;// 我们需要面积,但是用户输入的是长宽。// 所以需要在搜索面积前首先计算面积autofound{std::find_if(areas.begin(),areas.end(),// 声明一个仅 lambda 可见的变量// userArea 会被自动推断为 int.[userArea{width*height}](intknownArea){return(userArea==knownArea);})};if(found==areas.end()){std::cout<<"I don't know this area :(\n";}else{std::cout<<"Area found :)\n";}return0;}
#include<iostream>#include<string>// 返回一个 lambdaautomakeWalrus(conststd::string&name){// 按引用捕获 name 并返回一个lambdareturn[&](){std::cout<<"I am a walrus, my name is "<<name<<'\n';// 未定义行为};}intmain(){// 创建一个名为roofus的新的 walrus // sayName 是 makeWalrus 返回的 lambdaautosayName{makeWalrus("Roofus")};// 调用 makeWalrus 返回的 lambda sayName();return0;}
如果我们想要在使用lambda时仍然保证 name 可用,则需要在闭包中按值捕获该变量(显式指定或默认按值捕获)。
无意间拷贝可变的 lambda
因为lambda是对象,所以它们可以被复制。在某些情况下,这可能会导致问题。考虑以下代码:
1 2 3 4 5 6 7 8 9101112131415161718192021
#include<iostream>intmain(){inti{0};// Create a new lambda named countautocount{[i]()mutable{std::cout<<++i<<'\n';}};count();// invoke countautootherCount{count};// create a copy of count// invoke both count and the copycount();otherCount();return0;}
#include<iostream>#include<functional>voidmyInvoke(conststd::function<void()>&fn){fn();}intmain(){inti{0};// Increments and prints its local copy of @i.autocount{[i]()mutable{std::cout<<++i<<'\n';}};myInvoke(count);myInvoke(count);myInvoke(count);return0;}
#include<iostream>#include<functional>voidmyInvoke(conststd::function<void()>&fn){fn();}intmain(){inti{0};// Increments and prints its local copy of @i.autocount{[i]()mutable{std::cout<<++i<<'\n';}};// std::ref(count) 使得 count 被当做引用对待// 因此, 任何对其的拷贝都实际拷贝的是引用,确保始终只存在一个 countmyInvoke(std::ref(count));myInvoke(std::ref(count));myInvoke(std::ref(count));return0;}