本文介绍了C ++ 11 lambdas:成员变量capture gotcha的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请考虑以下代码:

#include <memory>
#include <iostream>

class A
{
public:
    A(int data) : data_(data)
    { std::cout << "A(" << data_ << ")" << std::endl; }
    ~A() { std::cout << "~A()" << std::endl; }
    void a() { std::cout << data_ << std::endl; }
private:
    int data_;
};

class B
{
public:
    B(): a_(new A(13)) { std::cout << "B()" << std::endl; }
    ~B() { std::cout << "~B()" << std::endl; }
    std::function<void()> getf()
    {
        return [=]() { a_->a(); };
    }
private:
    std::shared_ptr<A> a_;
};

int main()
{
    std::function<void()> f;
    {
        B b;
        f = b.getf();
    }
    f();
    return 0;
}

这里看起来像是捕获 a_ 按值的共享指针,但是当我在Linux(GCC 4.6.1)上运行它时,会打印:

Here it looks like I'm capturing a_ shared pointer by value, but when I run it on Linux (GCC 4.6.1), this is printed:

A(13)
B()
~B()
~A()
0

显然,0是错误的,因为A已经被破坏了。它看起来像实际被捕获,并用于查找 this-> a _ 。当我将捕获列表从 [=] 更改为 [=,a _] 时,我的怀疑被确认。然后输出正确的输出并且对象的生命周期如预期的那样:

Obviously, 0 is wrong, because A is already destroyed. It looks like this is actually captured and is used to look up this->a_. My suspicion is confirmed when I change the capture list from [=] to [=,a_]. Then the correct output is printed and the lifetime of the objects is as expected:

A(13)
B()
~B()
13
~A()

问题:

这种行为是由标准,实现定义还是未定义指定的?

Is this behaviour specified by the standard, implementation-defined, or undefined? Or I'm crazy and it's something entirely different?

推荐答案

是的。捕获成员变量总是通过捕获 this ;它是访问成员变量的唯一方法。在成员函数范围内,_ 等效于(* this).a _

Yes. Capturing member variables is always done via capturing this; it is the only way to access a member variable. In the scope of a member function a_ is equivalent to (*this).a_. This is true in Lambdas as well.

因此,如果你使用 this (隐式或显式)必须确保对象在lambda实例周围仍然有效。

Therefore, if you use this (implicitly or explicitly), then you must ensure that the object remains alive while the lambda instance is around.

如果要按值捕获它,您必须明确这样做:

If you want to capture it by value, you must explicitly do so:

std::function<void()> getf()
{
    auto varA = a_;
    return [=]() { varA->a(); };
}

如果您需要规格报价:

这篇关于C ++ 11 lambdas:成员变量capture gotcha的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-30 02:47