c++11 lambdas 捕获他们不使用的变量吗?

Posted

技术标签:

【中文标题】c++11 lambdas 捕获他们不使用的变量吗?【英文标题】:Do c++11 lambdas capture variables they don't use? 【发布时间】:2011-09-05 02:31:14 【问题描述】:

当我使用[=] 表示我希望通过 lambda 中的值捕获所有局部变量时,这会导致函数中的 all 局部变量被复制,还是全部复制lambda 使用的局部变量

所以,例如,如果我有:

vector<int> my_huge_vector(100000);
int my_measly_int;
some_function([=](int i) return my_measly_int + i; );

是否会复制 my_huge_vector,即使我不在 lambda 中使用它?

【问题讨论】:

【参考方案1】:

捕获列表中明确命名的每个变量都会被捕获。默认捕获将仅捕获 (a) 未在捕获列表中明确命名的变量和 (b) used 在 lambda 表达式的主体中的变量。如果变量没有明确命名,并且您没有在 lambda 表达式中使用该变量,则不会捕获该变量。在您的示例中,my_huge_vector 未被捕获。

根据 C++11 §5.1.2[expr.prim.lambda]/11:

如果一个 lambda-expression 有一个关联的 capture-default 及其 compound-statement odr-uses this 或具有自动存储持续时间的变量,并且 odr-used 实体没有被显式捕获,则 odr-used 实体被称为隐式捕获。 p>

您的 lambda 表达式具有关联的默认捕获:默认情况下,您使用 [=] 按值捕获变量。

当且仅当使用了变量(在“使用”一词的单一定义规则意义上)是隐式捕获的变量。由于您根本没有在 lambda 表达式的主体(“复合语句”)中使用 my_huge_vector,因此它不会被隐式捕获。

继续 §5.1.2/14

一个实体被副本捕获如果

它是隐式捕获的,capture-default= 或如果 它是通过不包含&amp; 的捕获显式捕获的。

由于您的 my_huge_vector 没有被隐式捕获,也没有被显式捕获,因此根本不会通过复制或引用来捕获它。

【讨论】:

你有圣言吗? 不过,我要说的是,第 5.1.2 节的全部内容对于理解所有细节很重要。该部分定义了许多技术术语,并且由于 lambda 表达式的各个组成部分的定义必然纠缠在一起,因此很难抽出短引号来明确地说“这是 X,这就是 X 的原因”。跨度> 提醒您注意here,它表示不允许这样的优化,至少对于显式命名的变量是这样。我不知道在哪里画线。 @GManNickG:这是一些非常好的拖钓;-)。在我意识到它确实指向这个页面之前,我花了三下点击该链接...... :-O [无论如何,我明天早上进入办公室时会重新阅读语言规范并更新适当的答案。] 哦,废话,对不起!!!我的问题得到了回答,我的意思是链接here。那一定是非常令人困惑的。【参考方案2】:

不,my_huge_vector 不会被捕获。 [=] 表示所有使用的变量都被捕获在 lambda 中。

【讨论】:

是的。请注意,used 是一个技术词,实际上表示单一定义规则 used。因此,例如,考虑void f() const int size(10); [] int x[size]; ; 。在这里,size 没有被捕获,但这没关系,因为它没有在 ODR 意义上使用。 (Visual C++ 2010 不接受这个代码,要么是因为 VC10 发布后规范发生了变化,要么是由于一个 bug,估计这将在即将发布的版本中修复;g++ 4.5.1 接受它。) @JamesMcNellis dpn 别担心,MSVC 今天仍然是一堆臭屁。参看。 godbolt.org/z/vHnnCX(在 gcc 中查看 lulz)。那就是说;我不明白为什么出现在评估表达式中的任何标识符都不会被 ODR 使用。我认为这种情况肯定是 ODR 使用的,除非你的意思是它可以被解释为 constexpr 因此只有值是有用的?我不确定编译器是否假定 const 的东西不会发生变异。除非可能是超级激进的优化标志 OX 或其他东西。

以上是关于c++11 lambdas 捕获他们不使用的变量吗?的主要内容,如果未能解决你的问题,请参考以下文章

C ++ 11 lambda捕获`this`并按值捕获局部变量

在 C++11 中按值或引用使用 lambda 默认捕获的缺点?

如何使用lambda表达式捕获局部变量?

C++11:Lambda表达式

C++11lambda表达式精讲

C ++ 11 lambda作为成员变量?