C++ 为什么lambda中引用捕获的值被破坏?

C++ 为什么lambda中引用捕获的值被破坏?,c++,c++11,lambda,boost-asio,C++,C++11,Lambda,Boost Asio,可重复的示例: #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

可重复的示例:

#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)
        {

        }
    }
}
为什么呢?按值捕获正如我所期望的那样工作,但是为什么按引用捕获的行为是这样的呢


<强> > <强> >代码> int >代码>此处,仅举一个例子,考虑任何一个值不合格的大对象(例如消耗品拷贝)


为什么我要将
test1
test2
声明为
test1(const int&t\u a)
test2(const int&t\u a)
那么一切都正常工作了

引用的
t\u a
仅在
void test2(int t\u a)
范围内有效。
在您的情况下按值捕获.< /p> 不幸的是C++没有提供垃圾收集器(还),因此关闭的使用有些受损。

您可以通过引用进行捕获(例如,有多个闭包引用同一个捕获的对象),但是必须独立于闭包的生存期来保证对象的生存期;换句话说,如果通过引用捕获变量的lambda在被引用对象中幸存,并且在对象已被销毁时被调用,那么您将进入通常的“未定义行为”领域

这就是代码中发生的情况:捕获的变量是函数的一个参数,当调用闭包时,它已经被销毁

解决方案可以是按值捕获(在这种情况下,捕获对象被复制到闭包中,并且您没有生存期问题),也可以使用引用计数智能指针,例如
std::shared_ptr
,指向免费存储分配的对象,以确保只要闭包在引用(指向的)对象中存活对象也仍然存在。

因为引用悬空。它引用一个函数参数,该参数将在函数返回后立即停止存在。该函数在异步代码运行之前返回


只需通过值捕获
t\u a
,当然?

如果您在捕获值的生命周期之外使用它,您可以找到一个类似的示例
int
,这里只是一个示例,实际代码用于对象…@vladon:那么您应该在您的问题中包含该细节。谢谢,我包括了itOr
test2
也通过引用获取它的参数,然后OP需要确保传递给
test2
的任何对象的生存期都超过asio调用的生存期。你所说的
test2(int t_a)
范围是什么意思?我认为函数调用
io\u服务.post
test2()
的主体内属于函数
test2
io\u服务的范围。post(…)注册函数,而
io\u服务.run()
调用它。再过一刻:为什么我要将
test1
test2
声明为
test1(const int&t_a)
test2(const int&t_a)
都正常工作了吗?@vladon:纯粹的机会,有效。好吧,这取决于你将这些引用绑定到什么。我们不知道引用的生命周期是什么。原因是在这种情况下,引用捕获的变量在
main
中,并且仍然足够活跃。
in test2: t_a = 42
in test2 post lambda: t_a = 16451253
in test1: t_a = 16451253
Press any key to continue . . .