微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

通过 init 捕获的默认 lambda 捕获模式会是什么样的?

如何解决通过 init 捕获的默认 lambda 捕获模式会是什么样的?

使用 lambdas,在 C++11 中,我们可以将认捕获模式设置为 by-value/by-ref,例如[=]/[&],可选后跟显式捕获,按引用/按值,用于某些变量,例如[=,&this_is_by_ref][&,this_is_by_value]

在 C++14 中,我们还可以通过移动进行显式捕获,例如[y = std::move(x)]

Effective Modern C++中,第 32 条,第 3 段,我读了

你不能用初始化捕获表达的一件事是认捕获模式,[…]

作者最有可能指的是什么?

我们已经有办法通过复制或引用来捕获我们需要的所有变量。为什么我们要用 x = y 形式来表达?

也许作者只是指“认移动捕获”?在列出正文中使用的所有变量时,它会像 [x = std::move(x),y = std::move(y),…] 一样工作吗?

解决方法

该段落指出不可能将 init 捕获与默认捕获模式([&] 或 [=])相结合,并且没有用于移动语义的新默认捕获模式。

我们已经有办法通过复制或通过 参考。为什么我们要用 x = y 形式来表达它?

你的想法是对的。将 init 捕获与默认捕获相结合将具有与旧的默认捕获方式相同的行为。也许这就是它被省略的原因。然而 init-capture 可以做新的事情,这是以前做不到的。 (比如给一个新变量赋值)

也许作者只是指“默认移动捕获”? 像 [x = std::move(x),y = std::move(y),...] 列出了正文中使用的所有变量?

这也是真的。

为了更好地理解 init capture 的新可能性,我给你这个小例子。假设您想用 0 到 n 的值填充一个向量。使用 lambda 执行此操作的旧方法是:

std::vector<int> vec;
int i = 0;
std::generate_n(std::back_inserter(vec),n,[i]()mutable{
    return i++;
});

现在使用 init capture,您可以在 lambda 捕获中对计数变量进行值初始化:

std::vector<int> vec;
std::generate_n(std::back_inserter(vec),[i=0]()mutable{
    return i++;
});

这在以前是不可能的,并且在很多地方都很有用。

,

"init capture" 是 [z = y] 的捕获风格。

您无法用这种捕捉方式表达的唯一捕捉方式是默认捕捉模式。即:

[&,z=y]{ /* some code */ }

此处 & 使用旧式捕获语法。它表示我们有一个默认的捕获模式。 z=y 是新式的“初始化捕获”。

没有办法使用“init capture”来表达默认的捕获模式。

任何您使用旧式捕获语法执行的其他操作,您都可以使用 init 捕获语法进行复制。

即:

[x=x]{ /* some code */ }

是另一种表达方式

[x]{ /* some code */ }

[&x=x]{ /* some code */ }

是另一种表达方式

[&x]{ /* some code */ }

现在还没有那么深。

但是如果你的论点是“不要使用旧的捕获语法”,你应该证明你不再需要它了。并且您不需要旧的捕获语法,除非用于定义默认捕获模式。

,

@OutOfBound 的回答已经很好了。我只会从不同的角度表达类似的想法。

Scott Meyers 在第 32 条的前几段注意到:

  • 即使在采用标准的那一刻,C++11 中引入的捕获语法也不能令人满意。
  • 这样做的原因是缺乏使用移动语义(或者,例如,通过常量引用)进行捕获的方法,除非有一些笨拙、晦涩的解决方法。
  • 标准委员会本可以通过简单地扩展它来改进 C++11 语法的功能(我想,例如通过引入 [&&,&&x]),但最终选择了一种不同的、更通用的方法:他们引入了一个新语法(“C++14 语法”)。
  • 然后 Scott 注意到,原则上您几乎可以完全忘记旧的 C++11 语法而只使用 C++14 语法(具有捕获初始化的语法)。
  • 只有使用旧语法才能真正做到的唯一事情是定义默认捕获模式。
  • 然而,Scott 不鼓励 C++ 程序员使用默认的捕获模式(条款 31)。
  • 所以这句话的意思是:“实际上,C++ 程序员(或 C++ 语言)并不需要旧语法,我希望 C++ 中已经采用了新语法11"。

另请注意,新的捕获语法非常灵活,不仅可以表达您使用移动语义的意图,还可以用于常量引用(Scott 省略了后一点)和可变 lambda。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。