如何将这个javascript代码重写为C++ 11?

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()>.它不是外部函数的类型.外部函数只是用于创建内部范围的临时函数.

  • @Benjamin:我完全重写了我的答案来解释JavaScript代码的工作原理以及如何在C++中复制它的效果. (2认同)
  • 非常好的答案. (2认同)