在lambda表达式中使用未捕获的变量

4

我不太理解来自C++14标准草案N4140 5.1.2.12 [expr.prim.lambda]的一个例子。

A lambda-expression with an associated capture-default that does not explicitly capture this or a variable with automatic storage duration (this excludes any id-expression that has been found to refer to an initcapture’s associated non-static data member), is said to implicitly capture the entity (i.e., this or a variable) if the compound-statement:

  • odr-uses the entity, or
  • names the entity in a potentially-evaluated expression where the enclosing full-expression depends on a generic lambda parameter declared within the reaching scope of the lambda-expression.

[ Example:

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 ]

All such implicitly captured entities shall be declared within the reaching scope of the lambda expression.

[ Note: The implicit capture of an entity by a nested lambda-expression can cause its implicit capture by the containing lambda-expression (see below). Implicit odr-uses of this can result in implicit capture. —end note ]

我认为一个带有相关捕获默认值的lambda表达式应该禁止任何隐式捕获(并且这也由注释确认),因此#1调用将导致错误(关于使用未捕获的变量的错误)。那么它是如何工作的?f的第一个参数将是什么?如果在退出test()作用域后调用g会怎样?如果我将#1的签名更改为void(const int&)会怎么样?
--
更新:感谢大家对它如何工作的解释。稍后我将尝试找到并发布有关此情况的标准参考资料。

1
x 是一个常量表达式,由于引用的存在,它仅在 #2 处被 ODR 使用。 - Jarod42
1
换句话说,g 的行为就像它的主体是 { f(17); } - T.C.
1个回答

0

正如 T.C. 在他的评论中所说,#1 并不需要捕获,因为 x 在编译时已知,因此已经嵌入到 lambda 中。就像函数 f 在编译时已知一样,因此不需要被捕获。

我认为,如果您将 f 的签名更改为 int const &,那么您现在正在尝试传递指向堆栈上的常量的地址,因此受到更改的影响,并且它需要通过值或引用捕获 x


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接