在静态变量定义中捕获的引用

时间:2013-04-17 22:12:34

标签: c++ c++11

#include <iostream>

void foo(int k) {
    static auto bar = [&]{
        std::cout << k << std::endl;
    };
    bar();
}

int main () {
    foo(1); foo(2); foo(3); // output is correct: 1, 2, 3
}

检查函数 foo ,静态lambda如何通过引用捕获 k 。这似乎有效,并且更复杂的数据类型而不是 int 也会发生同样的情况。

这是预期的吗? 是否保证每次调用 foo k 的地址都相同,或者 UB

提前致谢,如果之前已经回复,我很抱歉(我确实试图找到类似的问题而没有成功)

2 个答案:

答案 0 :(得分:4)

这是未定义的行为

关于函数调用表达式及其参数初始化的C ++ 11标准的第5.2.2 / 4节:

  

[...] 参数的生命周期在它所在的函数结束时   是定义的回报。每个参数的初始化和销毁​​都发生在上下文中   调用功能。 [...]

因此,一旦函数调用返回,你的lambda将存储一个变为悬空的引用。

在这种情况下,实现是免费的(并且可能)在每个函数调用的同一地址创建函数参数,这可能是您观察预期输出的原因。

但是,标准没有规定这种行为 - 因此,你不应该依赖它(如果是这种情况,你的代码将因为3.8 / 7而合法)。

答案 1 :(得分:1)

在你的例子中它可能“正常工作”的原因是调用堆栈总是以相同的方式排列。试试这个,看看你是否仍然得到“预期”的输出。

#include <iostream>

void foo(int k) {
    static auto bar = [&]{
        std::cout << k << std::endl;
    };
    bar();
}

void baz(int k) {
    std::cout << "baz: ";
    foo(k);
}

int main () {
    foo(1); baz(2); foo(3);
}