C++ lambda对象的地址作为函数的参数

Joã*_*ael 7 c++ lambda c++11

根据我的经验,似乎要么:

  • 在调用之后,在函数调用内创建的lambda表达式将被销毁
  • 调用一个函数,该函数期望std::function从lambda中创建一个临时对象(std :: function),并在调用后销毁该对象

使用以下代码片段可以观察到此行为:

const function<void()>* pointer;

void a(const function<void()> & f)
{
    pointer = &f;
}

void b()
{
    (*pointer)();
}

int main()
{
    int value = 1;
    std::cout << &value << std::endl;

    // 1: this works    
    function<void()> f = [&] () { std::cout << &value << std::endl; };
    a(f);

    // 2: this doesn't
    a([&] () { std::cout << &value << std::endl; });

    /* modify the stack*/
    char data[1024];
    for (int i = 0; i < 1024; i++)
        data[i] = i % 4; 

    b();

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在第二种情况下究竟发生了什么?是否有正确的方法在a()不创建显式std::function对象的情况下调用?

编辑::这两个版本(1和2)编译恰到好处但产生不同的输出:

版本1:

0x7fffa70148c8
0x7fffa70148c8
Run Code Online (Sandbox Code Playgroud)

版本2:

0x7fffa70148c8
0
Run Code Online (Sandbox Code Playgroud)

Gri*_*zly 3

如果您创建临时文件,它将在行尾消失。正如您正确指出的那样,这意味着存储指向它的指针是一个坏主意。

如果你想存储一个指向 a 的指针std::function(或者其他任何东西),你需要确保它的生命周期在你停止使用该指针之前不会结束。这意味着您确实需要一个类型为的命名对象std::function

至于第二种情况发生的情况:您创建一个临时 lambda 来传递给函数。由于该函数需要 a ,因此将从 lambda 创建std::function一个临时值。std::function两者都将在生产线末端被摧毁。因此,您现在有一个指向已销毁的临时对象的指针,这意味着尝试使用指向的对象将使您坚定地进入未定义的行为领域。