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

标签 c++ c++11 lambda

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

  • 在函数调用中创建的 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 对象的 C++ 地址作为函数的参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13788590/

相关文章:

c++ - 我可以从基于 for 循环的范围内获取项目的索引吗?

java.util.stream 与 ResultSet

c++ - C++无法弄清楚为什么它会给出误报(newbie)

c++ - 将转换范围缩小到更大的类型(然后再返回)

c++ - 在并发运行时中,我可以将 parallel_invoke 或 task_group 与非常量函数对象一起使用吗?

c++ - 如何找出 cstyle cast 的实际作用?

c# - C# 中 lambda 的实际类型是什么?

c# - 如何删除 lambda 事件处理程序

c++ - 在 C++ 中,构造函数是在对象创建之前还是之后调用的?

c++ - Rcpp:通过引用将行附加到数据框