函數對象(function object)是指一個類重載函數運算符"()"後,使用類變量調用函數運算符時,其行為類似函數調用,是以也稱為仿函數(functor)。
lambda表達式是函數對象的文法糖,使用三種括号來定義:
[](){};
[]内可以是空白,表示不捕獲任何lambda表達式外部的任何變量,其内也可以聲明需要捕獲的lambda表達式外部的變量,可以是值捕獲,也可以是引用捕獲。
()内用于定義lambda表達式的參數;
{}内用于定義語句體,相當于函數的函數體。
lambda表達式直接調用的文法形式:
[](){}(); // 第二對小括号()表達式表示調用,内部的值對應第一對小括号()内聲明的參數。
操作參數化是指用函數指針、函數對象或lambda表達式做函數參數。
lambda表達式這種文法形式的引入主要用于操作參數化。
1 成員函數與函數對象
成員函數:
#include <iostream>
class AddNum{
public:
AddNum(int num):num_(num){}
int addNum(int x)const{
return num_+x;
}
private:
int num_;
};
int main() {
auto add_num = AddNum(10);
auto x = add_num.addNum(5);
std::cout<<"x:"<<x<<std::endl;
return 0;
}
将成員函數改寫為函數對象的形式:
#include <iostream>
class AddNum{
public:
AddNum(int num):num_(num){}
int operator()(int x)const{
return num_+x;
}
private:
int num_;
};
int main() {
auto add_num = AddNum(10);
auto x = add_num(5);
std::cout<<"x:"<<x<<std::endl;
return 0;
}
2 從函數對象到lambda表達式
lambda表達式:
#include <iostream>
int main() {
auto x = [num=10](int x){return num + x;}(5);
std::cout<<"x:"<<x<<std::endl;
return 0;
}
lambda表達式是函數對象的文法糖。
也可以對lambda表達式進行命名,命名後可以如同函數一樣調用:
#include <iostream>
int main() {
auto add_num = [num=10](int x){return num + x;};
auto x = add_num(5);
std::cout<<"x:"<<x<<std::endl;
return 0;
}
auto推導的lambda表達式類型相當于以下類型:
#include <iostream>
#include <functional>
int main() {
std::function<int(int)> add_num = [num=10](int x){return num + x;};
auto x = add_num(5);
std::cout<<"x:"<<x<<std::endl;
return 0;
}
3 操作參數化
操作參數化也就是用函數指針、函數對象或lambda表達式做函數參數。
如for_each()函數:
template<class InputIterator, class Function>
Function for_each(InputIterator first, InputIterator last, Function fn)
{
while(first!=last) {
fn (*first); // fn是for_each的參數,first也是,同時也是fn的參數
++first;
}
return fn; // or, since C++11: return move(fn);
}
3.1 使用函數指針讓操作參數化
#include <iostream>
#include <vector>
#include <algorithm>
void print_int(int x){
std::cout<<"x: "<<x<<std::endl;
}
int main() {
std::vector<int> arr = {1,3,5,7,9};
std::for_each(arr.begin(),arr.end(),print_int);
return 0;
}
3.2 使用函數對象讓操作參數化
#include <iostream>
#include <vector>
#include <algorithm>
struct print_int{
void operator()(int x){
std::cout<<"x: "<<x<<std::endl;
}
};
int main() {
std::vector<int> arr = {1,3,5,7,9};
std::for_each(arr.begin(),arr.end(),print_int());
return 0;
}
3.3 使用lambda表達式讓操作參數化
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> arr = {1,3,5,7,9};
std::for_each(arr.begin(),arr.end(),[](int x){std::cout<<"x: "<<x<<std::endl;});
return 0;
}
4 lambda表達式還可以捕獲表達式外部的變量
4.1 按值捕獲
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
int times = 2;
int others = 3;
std::vector<int> arr = {1,3,5,7,9};
std::for_each(arr.begin(),arr.end(),[times](int x){std::cout<<"x: "<<x*times<<std::endl;}); // 按值捕獲times
return 0;
}
也可以全部按值捕獲:
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
int times = 2;
int others = 3;
std::vector<int> arr = {1,3,5,7,9};
std::for_each(arr.begin(),arr.end(),[=](int x){std::cout<<"x: "<<x*times*others<<std::endl;}); // [=]表示全部按值捕獲
return 0;
}
4.2 按引用捕獲
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
int times = 2;
int others = 3;
std::vector<int> arr = {1,3,5,7,9};
std::for_each(arr.begin(),arr.end(),[×](int x){std::cout<<"x: "<<x*++times<<std::endl;}); // [×]表示按引用捕獲times
return 0;
}
也可以全部按引用捕獲:
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
int times = 2;
int others = 3;
std::vector<int> arr = {1,3,5,7,9};
std::for_each(arr.begin(),arr.end(),[&](int x){std::cout<<"x: "<<x*++times*++others<<std::endl;}); // [&]表示全部引用
return 0;
}
ref
https://www.bilibili.com/video/BV1oW4y1z7nq
https://www.bilibili.com/video/BV1CD4y1y73q
-End-