考虑一下:
#include <iostream>
#include <functional>
std::function<void()> task;
int x = 42;
struct Foo
{
int& x;
void bar()
{
task = [=]() { std::cout << x << '\n'; };
}
};
int main()
{
{
Foo f{x};
f.bar();
}
task();
}
我的直觉是,当执行任务时,实际的指示对象仍然存在,我们在遇到lambda时得到一个新绑定的引用,一切都很好。
但是,在我的GCC 4.8.5(CentOS 7)上,我看到一些行为(在一个更复杂的程序中)表明这是UB,因为f
和参考f.x
本身已经死了。是吗?
答案 0 :(得分:10)
要捕获成员引用,您需要使用以下语法(在C ++ 14中引入):
struct Foo
{
int & m_x;
void bar()
{
task = [&l_x = this->m_x]() { std::cout << l_x << '\n'; };
}
};
这种方式l_x
是一个int &
存储在关闭状态中,引用int
值m_x
引用的Foo
并且不受struct Foo
{
int & m_x;
void bar()
{
int * p_x = &m_x;
task = [=]() { std::cout << *p_x << '\n'; };
}
};
影响超出范围。
在C ++ 11中,我们可以通过值捕获指针来解决此功能的缺失:
{{1}}
答案 1 :(得分:3)
您可以通过创建引用的本地副本和显式捕获来捕获C ++ 11中的引用成员,以避免捕获this
:
void bar()
{
decltype(x) rx = x; // Preserve reference-ness of x.
static_assert(std::is_reference<decltype(rx)>::value, "rx must be a reference.");
task = [&rx]() { std::cout << rx << ' ' << &rx << '\n'; }; // Only capture rx by reference.
}