1

使用 lambdas,在 C++11 中,我们可以将默认捕获模式设置为按值/按引用,例如[=]/ [&],对于某些变量,可选地后跟显式捕获,按引用/按值,例如[=,&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), …]与列出的正文中使用的所有变量一样的东西?

4

3 回答 3

4

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

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

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

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

这也是真的。

为了更好地理解初始化捕获的新可能性,我举了一个小例子。假设您想用从 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), n, [i=0]()mutable{
    return i++;
});

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

于 2021-01-06T10:20:08.967 回答
2

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

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

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

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

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

您使用旧式捕获语法所做的任何其他事情,您都可以使用 init 捕获语法进行复制。

IE:

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

是另一种表达方式

[x]{ /* some code */ }

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

是另一种表达方式

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

现在这不是那么深。

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

于 2021-01-06T15:36:44.740 回答
1

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

Scott Meyers 在第 32 项的前几段中指出:

  • 即使在采用标准的那一刻,C++11 中引入的捕获语法也被认为不能令人满意。
  • 其原因是缺乏使用移动语义(或者,例如,通过 const 引用)进行捕获的方法,也许除了一些尴尬、晦涩的解决方法。
  • [&&, &&x]标准委员会本可以通过简单的扩展来改进 C++11 语法的功能(我猜,例如通过引入句法”)。
  • 然后 Scott 注意到,原则上您几乎可以完全忘记旧的 C++11 语法,而只使用 C++14 语法(带有捕获初始化的语法)。
  • 仅使用旧语法真正可以做的唯一一件事是定义默认捕获模式。
  • 然而,Scott 不鼓励 C++ 程序员无论如何都使用默认的捕获模式(第 31 条)。
  • 所以这句话的意思是:“在实践中,C++ 程序员(或 C++ 语言)不需要旧语法,我希望新语法已经在 C++11 中采用”。

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

于 2021-01-06T15:24:54.790 回答