繁体   English   中英

C ++ lambda by-value捕获语义和允许的优化

[英]C++ lambda by-value capture semantics and allowed optimizations

当只有隐式捕获对象的某些数据成员被仿函数实际使用时,编译器允许从按值默认捕获中省略什么? 例如,

struct A {
  // some members we care about:
  char x;
  int y;
  // some huge amount of state we do not:
  std::array<bool, 200000> z;

  int foo() const { return y + 1 }
};

void bar() {
  A a;
  // must the entirety of a be copy captured, or is the compiler allowed to pick/prune?
  auto l1 = [=](){ std::cout << a.x << ", " << a.y << std::endl; };
  // ...
}

同样,如果早期评估允许省略更广泛的捕获?

void baz(int i) {
  A a2;
  a2.y = i;

  // capture fundamentally only needs 1 int, not all of an A instance.
  auto l2 = [=](){ std::cout << a.foo() << std::endl; }
}

至少在某些情况下,对元素进行部分与完整的副本捕获应该没有超出lambda大小的可见外部效果,但我不知道规范中的哪个位置寻找可以允许的优化的答案。

我认为,原则上,允许编译器以一种仅在as-if规则下捕获已使用成员的副本的方式对其进行优化。 [expr.prim.lambda]§2的相关部分:

[...]实现可以定义闭包类型与下面描述的不同,前提是这不会改变程序的可观察行为,只需更改:

  • 封闭类型的大小和/或对齐方式,
  • 封闭类型是否可以轻易复制,或者
  • 闭包类型是否为标准布局类。

但是,在检查闭包类型的sizeof()的快速测试中,主要编译器(clang,gcc,msvc)似乎都没有以这种方式优化闭包类型本身。

但应该注意的是,只有在实际存储从某个lambda表达式获取的对象时(例如在std::function ),这才真正成为一个问题。 通常情况下,lambda表达式的结果将仅用作某个函数模板的参数,然后丢弃。 在这种情况下,所有内容最终都被内联,优化器应该(并且在我的测试中做)只丢弃为从未引用的数据复制而生成的代码...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM