lambda函数对象中的静态变量如何工作? [英] How do static variables in lambda function objects work?

查看:112
本文介绍了lambda函数对象中的静态变量如何工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在使用lambda的函数的调用之间是否保留了lambda中使用的静态变量?还是在每个函数调用中再次创建函数对象?

Are static variables used in a lambda retained across calls of the function wherein the lambda is used? Or is the function object "created" again each function call?

无用的示例:

#include <iostream>
#include <vector>
#include <algorithm>

using std::cout;

void some_function()
{
    std::vector<int> v = {0,1,2,3,4,5};
    std::for_each( v.begin(), v.end(),
         [](const int &i)
         {
             static int calls_to_cout = 0;
             cout << "cout has been called " << calls_to_cout << " times.\n"
                  << "\tCurrent int: " << i << "\n";
             ++calls_to_cout;
         } );
}

int main()
{
    some_function();
    some_function();
}

此程序的正确输出是什么?
lambda是否捕获局部变量是否取决于事实? (它肯定会更改功能对象的基础实现,因此可能会产生影响)。是否允许行为不一致?

What is the correct output for this program? Is it dependent on the fact if the lambda captures local variables or not? (it will certainly change the underlying implementation of the function object, so it might have an influence) Is it an allowed behavioural inconsistency?

我不是在寻找:我的编译器输出...,这太新了,无法信任当前的实现IMHO。我知道要求标准报价似乎很受欢迎,因为世界上发现了这样的东西,但我仍然希望得到一个体面的来源。

I'm not looking for: "My compiler outputs ...", this is too new a feature to trust current implementations IMHO. I know asking for Standard quotes seems to be popular since the world discovered such a thing exists, but still, I would like a decent source.

推荐答案

tl; dr版本在底部。

tl;dr version at the bottom.

§5.1.2[expr .prim.lambda]


p1 lambda-expression

lambda引入程序lambda-declarator opt 复合语句

p1 lambda-expression:
lambda-introducer lambda-declaratoropt compound-statement

p3 的类型lambda-expression (也是闭包对象的类型)是一种唯一的,未命名的ununion类类型,称为闭包类型,其属性如下所述。此类不是聚合(8.5.1)。 闭包类型在包含相应 lambda-expression 的最小块范围,类范围或名称空间范围中声明。 (我的笔记:函数具有块范围。

p3 The type of the lambda-expression (which is also the type of the closure object) is a unique, unnamed nonunion class type — called the closure type — whose properties are described below. This class type is not an aggregate (8.5.1). The closure type is declared in the smallest block scope, class scope, or namespace scope that contains the corresponding lambda-expression. (My note: Functions have a block scope.)

p5 lambda的闭包类型 -expression 具有公共的内联函数调用运算符[...]

p5 The closure type for a lambda-expression has a public inline function call operator [...]

p7 > lambda-expression 的 compound-statement 产生函数调用运算符[...]

p7 The lambda-expression’s compound-statement yields the function-body (8.4) of the function call operator [...]

由于复合语句直接作为函数调用操作符的主体,并且闭包类型在最小(最内部)范围内定义,因此相同如下所示:

Since the compound-statement is directly taken as the function call operator's body, and the closure type is defined in the smallest (innermost) scope, it's the same as writing the following:

void some_function()
{
    struct /*unnamed unique*/{
      inline void operator()(int const& i) const{
        static int calls_to_cout = 0;
        cout << "cout has been called " << calls_to_cout << " times.\n"
             << "\tCurrent int: " << i << "\n";
        ++calls_to_cout;

      }
    } lambda;
    std::vector<int> v = {0,1,2,3,4,5};
    std::for_each( v.begin(), v.end(), lambda);
}

这是合法的C ++,允许函数具有静态局部变量。

Which is legal C++, functions are allowed to have static local variables.

§3.7.1[basic.stc.static]


p1所有没有动态存储持续时间,没有线程存储持续时间以及非本地变量的所有变量都具有静态存储持续时间。 这些实体的存储应在程序执行期间一直存储

p3关键字 static 可用于声明具有静态存储持续时间的局部变量。 [...]

p3 The keyword static can be used to declare a local variable with static storage duration. [...]

§6.7[stmt.dcl] p4 < br>
(这涉及在块范围内以静态存储持续时间初始化变量。)

§6.7 [stmt.dcl] p4
(This deals with initialization of variables with static storage duration in a block scope.)


[...]否则,该变量将在控件第一次通过其声明时进行初始化; [...]

[...] Otherwise such a variable is initialized the first time control passes through its declaration; [...]






要重申:


To reiterate:


  • lambda表达式的类型在最内部的范围内创建。

  • 不是不是新创建的对于每个函数调用(这没有意义,因为上面的示例中包含了封闭的函数体)。

  • 它遵循(几乎)正常的类/结构的所有规则(只是某些有关的东西是不同的),因为它是非工会类类型。

  • The type of a lambda expression is created in the innermost scope.
  • It is not created anew for each function call (that wouldn't make sense, since the enclosing function body would be as my example above).
  • It obeys (nearly) all the rules of normal classes / structs (just some stuff about this is different), since it is a non-union class type.

现在我们已经保证,对于每个函数调用,闭包类型都是相同的,我们可以放心地说,静态局部变量也一样它是在第一次调用函数调用操作符时进行初始化的,并且一直存在到程序结束。

Now that we have assured that for every function call, the closure type is the same, we can safely say that the static local variable is also the same; it's initialized the first time the function call operator is invoked and lives until the end of the program.

这篇关于lambda函数对象中的静态变量如何工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆