C++ 什么是C++;11?
什么是C++11中的lambda表达式?我什么时候用?在引入之前,他们解决了哪类问题是不可能的 一些示例和用例将非常有用 问题 C++包含有用的通用函数,如C++ 什么是C++;11?,c++,lambda,c++11,c++-faq,C++,Lambda,C++11,C++ Faq,什么是C++11中的lambda表达式?我什么时候用?在引入之前,他们解决了哪类问题是不可能的 一些示例和用例将非常有用 问题 C++包含有用的通用函数,如std::for_each和std::transform,非常方便。不幸的是,它们的使用也非常麻烦,特别是如果您想要应用的是特定函数所特有的 #include <algorithm> #include <vector> namespace { struct f { void operator()(int)
std::for_each
和std::transform
,非常方便。不幸的是,它们的使用也非常麻烦,特别是如果您想要应用的是特定函数所特有的
#include <algorithm>
#include <vector>
namespace {
struct f {
void operator()(int) {
// do something
}
};
}
void func(std::vector<int>& v) {
f f;
std::for_each(v.begin(), v.end(), f);
}
但是,这是不允许的,f
不能传递给C++03中的函数
新的解决方案
C++11引入了lambda,它允许您编写一个内联匿名函子来替换结构f。对于小的简单示例,它可以更清晰地阅读(它将所有内容保存在一个位置),并且可能更易于维护,例如以最简单的形式:
void func3(std::vector<int>& v) {
std::for_each(v.begin(), v.end(), [](int) { /* do something here*/ });
}
“捕获”变量
到目前为止,除了在lambda中传递给lambda的内容之外,我们没有使用任何其他内容,但是我们也可以在lambda中使用其他变量。如果要访问其他变量,可以使用capture子句(表达式的[]
),该子句在这些示例中尚未使用,例如:
void func5(std::vector<double>& v, const double& epsilon) {
std::transform(v.begin(), v.end(), v.begin(),
[epsilon](double d) -> double {
if (d < epsilon) {
return 0;
} else {
return d;
}
});
}
void func5(std::vector&v,const double&epsilon){
std::transform(v.begin(),v.end(),v.begin(),
[ε](双d)->双d{
if(d
您可以通过引用和值进行捕获,可以分别使用&
和=
进行指定:
通过引用捕获[&epsilon]
通过引用捕获lambda中使用的所有变量[&]
按值捕获lambda中使用的所有变量[=]
捕获类似[&]的变量,但按值捕获epsilon[&,epsilon]
捕获类似[=]的变量,但epsilon通过引用[=,&epsilon]
operator()
是const
,这意味着当您默认访问它们时,捕获将是const
。这意味着每个具有相同输入的调用都会产生相同的结果,但是您可以请求生成的操作符()
不是问题所在
C++包含有用的通用函数,如std::for_each
和std::transform
,非常方便。不幸的是,它们的使用也非常麻烦,特别是如果您想要应用的是特定函数所特有的
#include <algorithm>
#include <vector>
namespace {
struct f {
void operator()(int) {
// do something
}
};
}
void func(std::vector<int>& v) {
f f;
std::for_each(v.begin(), v.end(), f);
}
但是,这是不允许的,f
不能传递给C++03中的函数
新的解决方案
C++11引入了lambda,它允许您编写一个内联匿名函子来替换结构f。对于小的简单示例,它可以更清晰地阅读(它将所有内容保存在一个位置),并且可能更易于维护,例如以最简单的形式:
void func3(std::vector<int>& v) {
std::for_each(v.begin(), v.end(), [](int) { /* do something here*/ });
}
“捕获”变量
到目前为止,除了在lambda中传递给lambda的内容之外,我们没有使用任何其他内容,但是我们也可以在lambda中使用其他变量。如果要访问其他变量,可以使用capture子句(表达式的[]
),该子句在这些示例中尚未使用,例如:
void func5(std::vector<double>& v, const double& epsilon) {
std::transform(v.begin(), v.end(), v.begin(),
[epsilon](double d) -> double {
if (d < epsilon) {
return 0;
} else {
return d;
}
});
}
void func5(std::vector&v,const double&epsilon){
std::transform(v.begin(),v.end(),v.begin(),
[ε](双d)->双d{
if(d
您可以通过引用和值进行捕获,可以分别使用&
和=
进行指定:
通过引用捕获[&epsilon]
通过引用捕获lambda中使用的所有变量[&]
按值捕获lambda中使用的所有变量[=]
捕获类似[&]的变量,但按值捕获epsilon[&,epsilon]
捕获类似[=]的变量,但epsilon通过引用[=,&epsilon]
operator()
是const
,这意味着当您默认访问它们时,捕获将是const
。这会导致使用相同输入的每个调用都会产生相同的结果,但是您可以请求生成的运算符()
不是const
什么是lambda函数?
<λ函数的C++概念起源于λ演算和函数规划。lambda是一个未命名的函数,对于不可能重用且不值得命名的短代码片段非常有用(在实际编程中,而不是理论上)
在C++中,λ函数定义为这样的
[]() { } // barebone lambda
或者在它所有的荣耀里
[]() mutable -> T { } // T is the return type, still lacking throw()
[]
是捕获列表,()
是参数列表,{}
是函数体
捕获列表
捕获列表定义了lambda外部的哪些内容在函数体内部可用以及如何使用。
它可以是:
[x,&y]
参数列表
参数列表与其他C++函数相同。 职能机构 实际调用lambda时将执行的代码
返回类型扣除 如果lambda只有一个return语句,则返回类型可以省略,并具有隐式类型decltype(return\u语句)
易变的
如果lambda被标记为可变的(例如,[]()可变的{}
),则允许对已被标记的值进行变异
[]() mutable -> T { } // T is the return type, still lacking throw()
int x = 4;
auto y = [&r = x, x = x+1]()->int {
r += 2;
return x+2;
}(); // Updates ::x to 6, and initializes y to 7.
auto ptr = std::make_unique<int>(10); // See below for std::make_unique
auto lambda = [ptr = std::move(ptr)] {return *ptr;};
auto lambda = [](auto x, auto y) {return x + y;};
[&](){ ...your code... }(); // immediately executed lambda expression
{ ...your code... } // simple code block
int a = []( int b ){ int r=1; while (b>0) r*=b--; return r; }(5); // 5!
[&]( std::function<void()> algorithm ) // wrapper section
{
...your wrapper code...
algorithm();
...your wrapper code...
}
([&]() // algorithm section
{
...your algorithm code...
});
auto algorithm = [&]( double x, double m, double b ) -> double
{
return m*x+b;
};
int a=algorithm(1,2,3), b=algorithm(4,5,6);
void apply(void (*f)(int)) {
f(10);
f(20);
f(30);
}
int col=0;
void output() {
apply([](int data) {
cout << data << ((++col % 10) ? ' ' : '\n');
});
}
void output(int n) {
int col=0;
apply([&col,n](int data) {
cout << data << ((++col % 10) ? ' ' : '\n');
});
}
#include <functional>
#include <functional>
void apply(std::function<void(int)> f) {
f(10);
f(20);
f(30);
}
void output(int width) {
int col;
apply([width,&col](int data) {
cout << data << ((++col % width) ? ' ' : '\n');
});
}
auto x = [=](int arg1){printf("%i", arg1); };
void(*f)(int) = x;
f(1);
x(1);
[captureVar1,captureVar2](int arg1){}
[&captureVar1,&captureVar2](int arg1){}
[=](int arg1){} // capture all not-static vars by value
[&](int arg1){} // capture all not-static vars by reference
[=,&Param2](int arg1){}
[&,Param2](int arg1){}
[=](int arg1)->trailing_return_type{return trailing_return_type();}
auto toFloat = [](int value) { return float(value);};
auto interpolate = [min = toFloat(0), max = toFloat(255)](int value)->float { return (value - min) / (max - min);};
void process_z_vec(vector<int>& vec)
{
auto print_2d = [](const vector<int>& board, int bsize)
{
for(int i = 0; i<bsize; i++)
{
for(int j=0; j<bsize; j++)
{
cout << board[bsize*i+j] << " ";
}
cout << "\n";
}
};
// Do sth with the vec.
print_2d(vec,x_size);
// Do sth else with the vec.
print_2d(vec,y_size);
//...
}
void print_modulo(const vector<int>& v, ostream& os, int m) // output v[i] to os if v[i]%m==0
{
for_each(begin(v),end(v),
[&os,m](int x) {
if (x%m==0) os << x << '\n';
});
}
class Modulo_print {
ostream& os; // members to hold the capture list int m;
public:
Modulo_print(ostream& s, int mm) :os(s), m(mm) {}
void operator()(int x) const
{
if (x%m==0) os << x << '\n';
}
};
void print_modulo(const vector<int>& v, ostream& os, int m)
// output v[i] to os if v[i]%m==0
{
class Modulo_print {
ostream& os; // members to hold the capture list
int m;
public:
Modulo_print (ostream& s, int mm) :os(s), m(mm) {}
void operator()(int x) const
{
if (x%m==0) os << x << '\n';
}
};
for_each(begin(v),end(v),Modulo_print{os,m});
}
void print_modulo(const vector<int>& v, ostream& os, int m)
// output v[i] to os if v[i]%m==0
{
auto Modulo_print = [&os,m] (int x) { if (x%m==0) os << x << '\n'; };
for_each(begin(v),end(v),Modulo_print);
}
void TestFunctions::simpleLambda() {
bool sensitive = true;
std::vector<int> v = std::vector<int>({1,33,3,4,5,6,7});
sort(v.begin(),v.end(),
[sensitive](int x, int y) {
printf("\n%i\n", x < y);
return sensitive ? x < y : abs(x) < abs(y);
});
printf("sorted");
for_each(v.begin(), v.end(),
[](int x) {
printf("x - %i;", x);
}
);
}
int main()
{
// Lambda & auto
int member=10;
auto endGame = [=](int a, int b){ return a+b+member;};
endGame(4,5);
return 0;
}
int main()
{
int member = 10;
class __lambda_6_18
{
int member;
public:
inline /*constexpr */ int operator()(int a, int b) const
{
return a + b + member;
}
public: __lambda_6_18(int _member)
: member{_member}
{}
};
__lambda_6_18 endGame = __lambda_6_18{member};
endGame.operator()(4, 5);
return 0;
}