可重复的例子:
#include <iostream>
#include <boost/asio/io_service.hpp>
boost::asio::io_service io_service;
void test1(int t_a)
{
std::cout << "in test1: t_a = " << t_a << std::endl;
}
void test2(int t_a)
{
std::cout << "in test2: t_a = " << t_a << std::endl;
io_service.post([&t_a]()
{
std::cout << "in test2 post lambda: t_a = " << t_a << std::endl;
test1(t_a);
});
}
int main(int, char**)
{
int a = 42;
for (;;) {
try
{
test2(a);
io_service.run();
break;
}
catch (std::exception & e)
{
}
}
}
输出:
in test2: t_a = 42
in test2 post lambda: t_a = 16451253
in test1: t_a = 16451253
Press any key to continue . . .
为什么?按价值捕获正如我所期望的那样,但为什么通过引用捕获表现得像这样?
注意 int
这里仅举例说明,考虑任何通过值传递不好的大对象(例如,消耗性副本)
为什么我宣布test1
和test2
为test1(const int& t_a)
而test2(const int& t_a)
一切正常呢?
答案 0 :(得分:4)
t_a
的引用仅在void test2(int t_a)
范围内有效。
在您的情况下按值捕获。
答案 1 :(得分:1)
不幸的是,C ++还没有提供垃圾收集器,因此闭包的使用有些受损。
您可以通过引用捕获(例如,具有引用相同捕获对象的多个闭包),但必须保证对象的生命周期独立于闭包的生命周期;换句话说,如果通过引用捕获变量的lambda在引用的对象中存活并且在对象已经被销毁时被调用,那么你将进入通常的&#34;未定义的行为&#34;领域
这是你的代码中发生的事情:捕获的变量是函数的一个参数,当调用闭包时它已经被破坏了。
解决方案是按值捕获(在这种情况下,捕获对象是在闭包内复制而你没有生命周期问题)或使用例如像std::shared_ptr
这样的引用计数智能指针到一个免费商店分配的对象,以确保只要关闭存活引用(指向)对象也存活。
答案 2 :(得分:1)
因为引用是悬空。它引用一个函数参数,一旦函数返回就会停止存在。该函数在异步代码运行之前返回。
当然可以按价值捕捉t_a
吗?