Ben*_*min 3 javascript c++ lambda closures c++11
这是我在Javascript权威指南中看到的javascript闭包代码.我想把它写成C++ 11
var uniqueID1 = (function()
{
var id = 0;
return function() { return id++; };
})();
Run Code Online (Sandbox Code Playgroud)
这是我写的cpp代码.但它没有被编译.C++ 11可以表示相同的表达式吗?
auto c = []() -> int (*)() { int x = 0; return [&x]() -> int { return x++; }};
Run Code Online (Sandbox Code Playgroud)
我正在使用VS2010
编辑: 这是我制作的完整javascript示例代码.您可以轻松测试代码在Web浏览器中的工作方式.
<head>
<script language="javascript">
var uniqueID1 = (function()
{
var id = 0;
return function() { return id++; };
})();
var uniqueID2 = (function()
{
var id = 0;
return function() { return id++; };
})();
</script>
</head>
<body>
<input value = "uniqueid1" type="button" OnClick="alert(uniqueID1());"></input>
<input value = "uniqueid2" type="button" OnClick="alert(uniqueID2());"></input>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
Nic*_*las 19
好的,首先让我们分解你的JavaScript.
function()
{
var id = 0;
return function() { return id++; };
}
Run Code Online (Sandbox Code Playgroud)
这创建了一个功能.没有名称的函数,不带参数.调用此函数时,将返回一个新函数.内部函数可以访问本地范围的变量,该变量将成为该内部函数状态的一部分.
每次调用此函数时,它都将返回一个新函数.这个新功能将拥有自己的状态(var id = 0;毕竟必须做一些事情).外部函数的每次调用都将返回一个具有新状态的新函数.
这个:
(function()
{
var id = 0;
return function() { return id++; };
})
Run Code Online (Sandbox Code Playgroud)
将函数包含在一对括号中.这是运算符优先级规则所必需的,以允许它工作:
(function()
{
var id = 0;
return function() { return id++; };
})()
Run Code Online (Sandbox Code Playgroud)
这将创建一个函数,然后调用该函数.这就是最后一次()做的事情.它调用外部函数,它创建一个具有自己范围的内部函数并返回它.
在此表达式中,外部函数丢失.没了; 你不能再访问它了.你创建它的时间足够长,可以调用它,然后让它进入垃圾收集的垃圾桶.
鉴于所有这些,我们可以看到这句话:
var uniqueID1 = (function()
{
var id = 0;
return function() { return id++; };
})();
Run Code Online (Sandbox Code Playgroud)
创建外部函数,调用返回新函数的函数,然后将内部函数存储在一个名为的变量中uniqueID1.
如果您需要证明这是真的,请在HTML中尝试:
var uniqueMaker = function()
{
var id = 0;
return function() { return id++; };
};
var uniqueID1 = uniqueMaker();
var uniqueID2 = uniqueMaker();
Run Code Online (Sandbox Code Playgroud)
您将获得与复制粘贴版本相同的答案.
如果我们希望C++代码模仿这一点,我们需要使用适当的C++代码执行每一步.
一,内在功能.在C++中,词汇范围不存在.因此,您无法返回引用其他范围中的变量的函数.您只能返回一个具有来自另一个范围的变量副本的lambda .此外,除非您明确允许,否则lambdas无法修改范围.因此,内部代码必须如下所示:
int id = 0;
return [=]() mutable { return ++id; };
Run Code Online (Sandbox Code Playgroud)
这一切都很好,但现在我们需要创建一个lambda来返回这个有状态的lambda函数.在C++中,具有状态的函数与函数指针不同.由于lambda的类型是编译器定义的,因此无法输入其名称.因此,我们必须使用std::function外部函数的返回类型.
[]() -> std::function<int()>
{
int x = 0;
return [=]() mutable { return x++; };
}
Run Code Online (Sandbox Code Playgroud)
这会创建一个lambda函数,在调用时,它将返回一个具有自己状态的内部函数.独立于此函数的任何后续调用的状态.就像JavaScript示例一样.
现在,这还不够.请记住,您的JavaScript创建外部函数,调用它,并仅存储其返回值.外部函数本身被丢弃.所以我们需要模仿这个.幸运的是,这在C++中很容易; 它看起来就像JavaScript:
([]() -> std::function<int()>
{
int x = 0;
return [=]() mutable { return x++; };
})()
Run Code Online (Sandbox Code Playgroud)
最后,我们将其添加到变量中:
auto uniqueID1 = ([]() -> std::function<int()>
{
int x = 0;
return [=]() mutable { return x++; };
})();
Run Code Online (Sandbox Code Playgroud)
类型uniqueID1将是std::function<int()>.它不是外部函数的类型.外部函数只是用于创建内部范围的临时函数.