const static auto lambda与引用

时间:2015-06-23 10:06:13

标签: c++ c++11 lambda reference

在C ++ 11函数中使用一些本地lambda对象时,我很想将它们声明为const static auto lambda = ...,只是为了让编译器知道只需要一个std::function对象(并且可能会优化)调用和/或内联它)但我意识到在这种情况下通过引用捕获局部值会导致奇怪的行为。

请考虑以下代码:

void process(const Data& data, const std::function<void(DataElement&>& lambda) {
  ...
}

void SomeClass::doSomething()
{
  int foo = 0;

  const static auto lambda = [&foo] () { .... ++foo; .... }

  process(data, lambda);
}

这不适用于doSomething()的多次调用,但机制尚不清楚。

  • foo是否在第一次调用时绑定,然后保持绑定到堆栈地址,该地址在连续调用时变为无效?
  • 在这种情况下我是否被迫static

标准中指定了哪种行为?考虑到它是一个static变量,它在哪里构建?懒惰第一次调用doSomething()(以便第一次调用工作)或程序启动时?

2 个答案:

答案 0 :(得分:13)

当控制流首次到达其声明时,静态函数范围变量“懒洋洋地”初始化。这意味着通过引用捕获确实绑定到当前堆栈上的foo,并且当调用终止时,该绑定变为悬空。

不要试图过多地帮助编译器;使lambda static看起来像微优化,副作用非常严重。实际上创建一个闭包对象几乎没有任何开销,编译器可以轻松地内联它,无论它是否static

更不用说即使使用您的方法,您也无法保存创建std::function对象。 lambda表达式的类型是未命名的闭包对象, not std::function。因此,即使lambdastatic,也会在每次调用中创建std::function对象(除非整个内容都被内联)。

答案 1 :(得分:0)

  

这不适用于doSomething()的多次调用,但机制尚不清楚。

这是因为在堆栈上分配了foofoo的确切地址取决于导致调用doSomething的调用堆栈。换句话说,函数调用之间foo的地址可能不同,除非调用堆栈完全相同。