c++ - 什么时候在 lambda 中捕获 'this'?

标签 c++ c++11 lambda

我在一个类中有一个函数,它定义了一个 lambda 并将它存储在一个局部静态变量中:

class A
{
public:
    void call_print()
    {
        static auto const print_func = [this] {
            print();
        };

        print_func();
    };

    virtual void print()
    {
        std::cout << "A::print()\n";
    }
};

class B : public A
{
public:
    virtual void print() override
    {
        std::cout << "B::print()\n";
    }
};

我还执行了以下测试:

int main()
{
    A a;
    B b;

    a.call_print();
    b.call_print();
}

( Live Sample )

我期望打印的是:

A::print()
B::print()

但我真正得到的是:

A::print()
A::print()

(每个也打印相同的对象地址)

我怀疑这是由于 this 捕获造成的。我假设它会在调用时捕获 this 的值,但是它似乎在定义 lambda 时就被捕获了。

有人能解释一下 lambda 捕获的语义吗?他们什么时候真正被提供给函数?是所有捕获类型都相同,还是 this 是一个特例?删除 static 解决了这个问题,但是在我的生产代码中,我实际上将 lambda 存储在一个稍重的对象中,该对象代表我稍后插入信号的插槽。

最佳答案

这与 lambda 捕获的语义无关。这就是 static 的工作原理。

static 函数范围的变量被初始化一次。在你的整个程序中只有一个这样的对象。它将在第一次调用函数时被初始化(更具体地说,第一次执行 static 语句时)。因此,用于初始化 static 变量的表达式只会被调用一次。

因此,如果 static 函数范围的变量使用基于函数参数之一的数据(如 this)进行初始化,那么它只会从该函数的第一次调用。

您的代码创建了一个 lambda。它不会在每次调用函数时创建不同的 lambda。

您似乎想要的行为不是函数局部 static 变量,而是对象成员。因此,只需在类本身中放置一个 std::function 对象,如果它为空则让 call_print 对其进行初始化。

关于c++ - 什么时候在 lambda 中捕获 'this'?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38354923/

相关文章:

c++ - OpenGL 显示白框,而不是立方体

C++ 在不重定向输出的情况下运行批处理文件

c++ - 如何为 string_view 创建 (VC14) 调试可视化工具?

C++函数接受函数指针和非静态成员函数作为参数

c++ - 我的枚举不是类或命名空间

c# - 在 lambda 表达式中使用可变字段名称

c++ - 以 std::bitset 访问 std::uint8_t

c++ - 为什么 C 数组比 std::array 快这么多?

java - 如何使用 lambda 将 Map<String,String> 转换为 "key1:value1,key2:value2,.."

java - 使用 lambda 在函数中传递两个参数