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

从我的经验看来,无论是:

  • 在函数调用内部创建的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;
    }
    

    第二种情况究竟发生了什么? 有没有正确的方法来调用a()而不创建一个明确的std::function对象?

    编辑::这两个版本(1和2)编译正确,但导致不同的输出:

    版本1:

    0x7fffa70148c8
    0x7fffa70148c8
    

    版本2:

    0x7fffa70148c8
    0
    

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

    如果你想存储一个指向std::function (或者其他的东西)的指针,你需要确保它的生命周期不会停止,然后再停止使用指针。 这意味着你确实需要一个类型为std::function的命名对象。

    至于第二种情况发生了什么:您创建一个临时的lambda来传递给函数。 由于该函数需要一个std::function ,因此将从lambda创建一个临时std::function 。 这两个将在行结束时被销毁。 因此,您现在有一个指向已经销毁的临时指针,这意味着尝试使用指向的对象将使您牢固地进入未定义的行为区域。


    无国籍的lambda可以。 无状态lambda具有隐式转换为函数指针类型。

    另外,无论实际的可调用类型如何,都总是隐式转换为std :: function <>。

    但是,保持指向临时对象的问题仍然存在 。 我没有注意到在第一次阅读代码时。

    当然,这与std :: function无关。


    临时对象在创建语句结束时被销毁。您刚刚使用lambda进行了演示。

    你第一次通过的std函数不是一个临时的,所以它的持续时间和变量一样长。 它实际上存储了一个临时副本。

    要让你的拉姆达达不到一条线,你需要将它存储在某个地方并确定它的寿命。

    有很多方法可以做到这一点。 Std函数是一种基于类型擦除的存储方式 - 即存储std函数而不是指向std函数的指针。 将pointer的类型更改为非指针(非const),删除&指派给它时直接调用它。

    一般情况下,避免将const引用函数参数的地址作为临时绑定对象,除非在另一个过载中捕获右值引用的可能性。

    链接地址: http://www.djcxy.com/p/11583.html

    上一篇: C++ Address of lambda objects as parameters to functions

    下一篇: Click event listener