有状态lambda和无状态lambda

无状态 lambda

C++11标准中新增了 lambda 表达式,可以快速精简的方式构建函数对象,而且还支持闭包,可以简单方便的捕捉当前上下文的对象。由于闭包的存在,又反过来要求闭包本身不可缺省构造和拷贝(拷贝和移动构造函数标记为 deleted ),这样和普通函数对象有区别,影响其应用。

因此在C++20中,将有状态的 lambda (捕捉上下文对象形成闭包)和无状态的 lambda (不捕捉上下文对象)区分开来,然后放宽无状态 lambda 的限制,允许无状态 lambda 有缺省的构造函数和拷贝、移动构造函数,这样无状态 lambda 就更加像一个函数对象,可以在其他普通函数对象可以使用的场合中使用。

先看一下有状态 lambda 和无状态 lambda 的区别:

#include

using std::cout, std::endl;

int main( int argc, char * argv[] )

{

int mm = 10;

auto f1 = [ = ] ( int x, int y )

{

return x + y + mm;

}; // <1> 有状态lambda,捕捉上下文变量

auto f2 = [ = ] ( int x, int y )

{

return x + y;

}; // <2> 有状态lambda,虽然实际未使用上下文变量,但捕捉列表中声明了默认捕捉

auto f3 = [ ] ( int x, int y )

{

return x + y;

}; // <3> 无状态lambda

//int (*fp1)( int , int ) = f1; // <1> Error,有状态lambda不能当普通函数对象那样赋值给函数指针

//int (*fp2)( int , int ) = f2; // <2> Error,有状态lambda不能当普通函数对象那样赋值给函数指针

int (*fp3)( int , int ) = f3; // <3> OK,无状态lambda可以当普通函数对象那样赋值给函数指针

std::cout << fp3(10, 20) << std::endl;

return 0;

}

代码中的 f1 和 f2 都是有捕捉上下文变量,不管实际函数体中有没有用到上下文变量,都属于有状态 lambda ,因此不能复制给函数指针,而f3没有捕捉上下文变量,因此是无状态 lambda ,所以可以赋值给函数指针,以及用在其他普通函数对象可以使用的地方。

C++20放宽了无状态 lambda 的限制,允许有缺省的构造函数和拷贝、移动构造函数,就可以当普通的函数对象一样,用在容器等各种场合中:

#include

#include

#include

#include

int main(void)

{

auto f4 = [] (int x, int y)

{

return x + y;

};

std::map m1, m2;

m1[2] = "aa";

m1 = m2;

return 0;

}

在 C++17 中,由于拷贝构造函数被标记成 deleted ,所以不能用在容器中,在 C++20 标准改进之后,就没有限制了,可以像普通函数对象一样,用在容器中。

参考:

https://blog.csdn.net/weixin_42208901/article/details/113051466

https://www.modernescpp.com/index.php/more-lambdas-features-with-c-20

你可能感兴趣的:(C++20,有状态lambda,无状态lambda)