在lambda

时间:2016-08-03 18:07:02

标签: c++ lambda standards c++14

我无法理解C ++ 14标准草案N4140 5.1.2.12 [expr.prim.lambda]中的一个例子。

  

具有关联捕获默认值的lambda表达式,该表达式未显式捕获此变量或具有自动存储持续时间的变量(这排除了任何已发现引用initcapture关联的非静态数据成员的id表达式),据说如果复合语句:

隐式捕获实体(即这个或变量)      
      
  • odr - 使用实体,或
  •   
  • 在潜在评估表达式中命名实体,其中封闭的full-expression依赖于在lambda表达式的到达范围内声明的泛型lambda参数。
  •   
     

[例如:

void f(int, const int (&)[2] = {}) { } // #1
void f(const int&, const int (&)[1]) { } // #2
void test() {
  const int x = 17;
  auto g = [](auto a) {
    f(x); // OK: calls #1, does not capture x
  };
  auto g2 = [=](auto a) {
    int selector[sizeof(a) == 1 ? 1 : 2]{};
    f(x, selector); // OK: is a dependent expression, so captures x
  };
}
     

-end example]

     

所有这些隐式捕获的实体都应在lambda表达式的扩展范围内声明。

     

[注意:嵌套的lambda表达式对实体的隐式捕获可能导致其通过包含的lambda表达式进行隐式捕获(见下文)。隐含的odr用法可能导致隐式捕获。 - 后注]

我认为短语a lambda-expression with an associated capture-default的开头应该禁止任何隐式捕获(并且通过评论确认),因此#1调用会导致错误(关于不使用捕获变量)。它是如何工作的? f的第一个论点是什么?如果在退出g范围后调用test()该怎么办?如果我将#1签名更改为void(const int&)

,该怎么办?

-

upd:感谢大家解释它是如何工作的。稍后我会尝试查找并发布有关此案例的标准引用。

1 个答案:

答案 0 :(得分:0)

作为T.C.在他的评论中说,#1不需要捕获,因为x在编译时是已知的,因此被烘焙到lambda中。与在编译时知道函数f的方式不同,因此不需要捕获它。

我相信如果您将f的签名更改为int const &,您现在正在尝试传递堆栈上的常量的地址,因此可能会发生更改,并且会需要按值或引用捕获x