关于 c++ lambda 函数需要注意的点

lambda 函数 capture by reference 很好理解,就类似于 Functor, 会在 closure 中定义一些指针指向使用的对象地址。

然后 capture by value 通常也类似 Functor,会在 closure 中定义一些对象,然后将使用到的对象复制进 closure 中.

需要注意一点的是:

One other thing that is sometimes overlooked however, is that even when one uses a capture-by-value-lambda in a member function, it doesn’t create a copy of the used member variables, but only makes a copy of the this pointer.

所以,如果在类成员函数中使用 lambda 函数,而且是 capture by value, 那么其结果就是: 该 lambda 函数对一个类的成员变量 capture by this pointer, 也就是 capture by reference,而对一个类 非成员变量 则 capture by value.

例如:

#include <iostream>
#include <vector>

using namespace std;
struct Foo
{
    int a;
    std::vector<int> b;
};

class Test
{
    Foo foo; 
    public:
    void func()
    {
        int c = 10;
        Foo f;
        cout << "Out address of a(member): " << &foo.a << endl;
        cout << "Out address of b(menber): " << &foo.b << endl;
        cout << "Out address of c(non-member): " << &c << endl;
        cout << "Out address of d(non-member): " << &f << endl;
        auto lambda = [=]()
        {
            cout << "In address of a(member): " << &foo.a << endl;
            cout << "In address of b(menber): " << &foo.b << endl; 
            cout << "In address of b(non-member): " << &c << endl;
            cout << "In address of d(non-member): " << &f << endl;
        };
        
        lambda();
        
    }
    
};


int main()
{
    Test t;
    t.func();
   
    cout << "Out address of t: " << &t << endl;
    auto lambda = [=]()
    {
        cout << "In address of t: " << &t << endl;
    };
    lambda();
   
   return 0;
}

运行结果:

$g++ -std=c++11 -o main *.cpp
$main
Out address of a(member): 0x7fffedde7430        // 在 lambda 函数外成员地址
Out address of b(menber): 0x7fffedde7438
Out address of c(non-member): 0x7fffedde73ec    // 在 lambda 函数外 非 成员地址
Out address of d(non-member): 0x7fffedde73c0

In address of a(member): 0x7fffedde7430         // 在 lambda 函数内成员地址(与lambda外地址相同,by reference)
In address of b(menber): 0x7fffedde7438
In address of b(non-member): 0x7fffedde7398     // 在 lambda 函数内 非 成员地址(与lambda外地址不同, by value)
In address of d(non-member): 0x7fffedde73a0
Out address of t: 0x7fffedde7430
In address of t: 0x7fffedde7410

除了上面那个点,下面两个例子也需要特殊注意

e.g 1:
在 lambda 本体中删除该 instance 类似于在 class 成员函数中删除 this 指针。如果在 lambda 函数中删除自身,然后再去获取 capture by value 变量,会导致程序崩溃。(同理,需要注意 lambda 函数 capture by value 自身 shared_ptr 而导致循环引用的问题)

#include <iostream>
#include <memory>
#include <functional>

using namespace std;

int main()
{
    std::function<int(void)> func;
    
    
    int i = 2;
    int c = 5;
    
    {
        func = [=,&func,&i]() {
            int b =3;
            func = nullptr;  // here will destory the std::function
            i+=1;
            return i+b;  // i+b+c segment fault
        };
    }
    
  cout << "Hello World: " << func() << endl; 
   
  return 0;
}

e.g.2:
lambda 内的 static 变量被该 lambda 的所有 instance 共享;因为本质上 lambda 是一个class, 一个 class的所有对象共享其 static 变量;不要误以为每一个 lambda 都独享一份自己的static变量哈,这是错误的。

#include <iostream>
#include <vector>
#include <algorithm>

using std::cout;

void some_function()
{
    std::vector<int> v = {0,1,2,3,4,5};
    std::for_each( v.begin(), v.end(),
         [](const int &i)
         {
             static int calls_to_cout = 0;
             cout << "cout has been called " << calls_to_cout << " times.\n"
                  << "\tCurrent int: " << i << "\n";
             ++calls_to_cout;
         } );
}

int main()
{
    some_function();
    some_function();
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值