c++11新特性_C++20 新特性(11):lambda对this的捕捉改进

在 C++11 标准中增加了 lambda 表达式,先简单回顾一下 lambda 中的缺省捕捉,再看 C++20 对 this 的捕捉的改进。

a42f05d6c9960c0ffb28e9933b2932ca.png

lambda表达式的缺省捕捉

lambda表达式中,可以显式捕捉指定的变量,也可以进行隐含的缺省捕捉,缺省捕捉有两种方式:

  • &:表示按引用的方式进行捕捉
  • =:表示按值的方式进行捕捉,具体变量的值会复制一个拷贝,这个拷贝是const不可修改的。注意,按值捕捉变量的值,是定义 lambda 时候的值,而不是执行 lambda 时候的值。

在使用了缺省捕捉的同时,也可以对指定变量进行显式捕捉,但这个时候,捕捉的方式应该是不一样的,例如缺省是按引用方式捕捉,那么可以指定某些变量时按值的方式进行捕捉,但不能再指定某些变量重复的按引用方式捕捉。

int n = 0;int k = 0;auto f1 = [ = ] { return n + k; };  // <1> OK,缺省按值捕捉auto f2 = [ & ] { return ++n; };   // <2> OK,缺省按引用捕捉auto f3 = [ =, k ] { return n + k; };  // <3> Error,缺省按值捕捉,不能再单个变量按值捕捉auto f4 = [ =, &k ] { return n + k; };  // <4> OK,缺省按值捕捉,指定变量按引用捕捉auto f5 = [ &, k ] { return n + k; };    // <5> OK,缺省按引用捕捉,指定变量按值捕捉auto f6 = [ &, &k ] { return n + k; };  // <6> Error,缺省按引用捕捉,不能再单个变量按引用捕捉auto f7 = [ k, k ] { return n + k; };  // <7> Error,同一个变量不能捕捉两次,auto f8 = [ k, &k ] { return n + k; };  // <7> Error,同一个变量不能捕捉两次,不管是否按值还是按引用

C++20 中 lambda 对 this 的捕捉改进

在类的成员函数中定义 lambda 时,this 指针是个特殊情况。因为类的成员函数中,默认都可以通过 this 指针访问类的成员变量,因此在 C++11 中新增 lambda 的时候,要求 this 指针只能使用引用方式,并且要求使用 “ = ” 缺省按值捕捉时,其他变量按引用捕捉都应该使用 “ & ” 来表示引用,并且特别指出 [ =, this ] 的写法是不合法的。

但按引用方式访问类成员变量不一定能满足所有需求,因此在C++17中,增加了按值的方式访问类成员变量,也就是捕捉 *this 。

这样对按值还是按引用捕捉 this 带来了差异,因此在C++20中,要求对 this 的捕捉要显式说明,不在 “ = & ” 的缺省捕捉中。同时,原来的 [ =, this ] 语法是不合法的,现在也改成合法了。

#include class SA{public:     int m_x { 0 };        void func();};void SA::func(){    int n = 0;    int ret = 0;    n = 1; m_x = 2;    auto f1 = [ = ] ( int k ) -> int {        // n = 10;   // <1> 按值捕捉,不能修改        return n + k;    };    n = 100; m_x = 200;    ret = f1( 3 );    printf( "n %d, m_x %d, ret %d", n, m_x, ret );    n = 1; m_x = 2;    auto f2 = [ =, this ] ( int k ) -> int {  // <2> C++17不支持,C++20支持,访问类成员变量,要求显式捕捉 this        // n = 10;        m_x = 20;   // <3> this按引用捕捉,可以修改        return n + m_x + k;    };    n = 100; m_x = 200;    ret = f2( 3 );    printf( "n %d, m_x %d, ret %d", n, m_x, ret );    n = 1; m_x = 2;    auto f3 = [ =, *this ] ( int k ) -> int {        // n = 10;         // m_x = 20;  // <4> this按值捕捉,不能修改        return n + m_x + k;    };    n = 100; m_x = 200;    ret = f3( 3 );    printf( "n %d, m_x %d, ret %d", n, m_x, ret );    n = 1; m_x = 2;    auto f4 = [ & ] ( int k ) -> int {        n = 10;        return n + k;    };    n = 100; m_x = 200;    ret = f4( 3 );    printf( "n %d, m_x %d, ret %d", n, m_x, ret );        n = 1; m_x = 2;    auto f5 = [ &, this ] ( int k ) -> int {  // <5> this按引用捕捉,其实和缺省按引用捕捉时重复的,不过标准一直都要求允许        n = 10;        m_x = 20;        return n + m_x + k;    };    n = 100; m_x = 200;    ret = f5( 3 );    printf( "n %d, m_x %d, ret %d", n, m_x, ret );    n = 1; m_x = 2;    auto f6 = [ &, *this ] ( int k ) -> int {        n = 10;        // m_x = 20;  // <6> this 按值捕捉,不能修改        return n + m_x + k;    };    n = 100; m_x = 200;    ret = f6( 3 );    printf( "n %d, m_x %d, ret %d", n, m_x, ret );    return;}int main( int argc, char * argv[] ){    struct SA a1;    a1.func();    return 0;}

编译和输出的结果为:

[smlc@test code]$ g++ -std=c++20 a11.cpp[smlc@test code]$ ./a.outn 100, m_x 200, ret 4n 100, m_x 20, ret 24n 100, m_x 200, ret 6n 10, m_x 200, ret 13n 10, m_x 20, ret 33n 10, m_x 200, ret 15

【往期回顾】

C++20 新特性(10):字符串类型的改进

C++20 新特性(9):指针和数组相关的两个改进

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值