好的,首先让我们分解一下 JavaScript 的作用。
function()
{
var id = 0;
return function() { return id++; };
}
这创建了一个函数。没有名称、不带参数的函数。调用该函数时,将返回一个新函数。内部函数将有权访问本地范围的变量,并且该变量将是该内部函数状态的一部分。
每次调用该函数时,都会返回一个new功能。该新函数将有自己的状态(var id = 0;
毕竟,必须做点什么)。外部函数的每次调用都会返回一个具有新状态的新函数。
This:
(function()
{
var id = 0;
return function() { return id++; };
})
将函数括在一对括号中。这是运算符优先级规则所必需的,以使其发挥作用:
(function()
{
var id = 0;
return function() { return id++; };
})()
这创建了一个函数,然后calls功能。这就是最后的事()
做在最后。它调用外部函数,该函数创建一个具有自己作用域的内部函数并返回它。
在这个表达式中,外部函数is lost。它消失了;您无法再访问它。您创建它的时间刚好足以调用它,然后让它掉进垃圾收集的垃圾桶。
考虑到所有这些,我们可以看到这样的声明:
var uniqueID1 = (function()
{
var id = 0;
return function() { return id++; };
})();
创建外部函数,调用返回新函数的函数,然后存储inner变量中的函数称为uniqueID1
.
如果您需要证明这是真的,请在 HTML 中尝试以下操作:
var uniqueMaker = function()
{
var id = 0;
return function() { return id++; };
};
var uniqueID1 = uniqueMaker();
var uniqueID2 = uniqueMaker();
您将得到与复制粘贴版本相同的答案。
如果我们希望 C++ 代码模仿这一点,我们需要使用正确的 C++ 代码执行每个步骤。
首先,内部功能。在 C++ 中,不存在词法作用域。因此,您不能返回引用其他作用域中的变量的函数。您只能返回一个具有copy来自另一个作用域的变量。此外,除非您明确允许,否则 lambda 无法修改作用域。因此,内部代码必须如下所示:
int id = 0;
return [=]() mutable { return ++id; };
一切都很好,但现在我们需要创建一个 lambda 来返回这个有状态 lambda 函数。在 C++ 中,有状态的函数与函数指针不同。由于 lambda 的类型是编译器定义的,因此无法键入其名称。因此,我们必须雇用std::function
作为外部函数的返回类型。
[]() -> std::function<int()>
{
int x = 0;
return [=]() mutable { return x++; };
}
这将创建一个 lambda 函数,该函数在被调用时将返回一个具有自己状态的内部函数。独立于对此函数的任何后续调用的状态。就像 JavaScript 示例一样。
现在,这还不够。请记住,您的 JavaScript 创建外部函数、调用它并存储only它的返回值。外层函数itself被丢弃。所以我们需要模仿这个。幸运的是,这在 C++ 中很容易;它看起来就像 JavaScript:
([]() -> std::function<int()>
{
int x = 0;
return [=]() mutable { return x++; };
})()
最后,我们把它放在一个变量中:
auto uniqueID1 = ([]() -> std::function<int()>
{
int x = 0;
return [=]() mutable { return x++; };
})();
的类型uniqueID1
将std::function<int()>
。它不会是外部函数的类型。外部函数只是一个临时函数,用于创建内部作用域。