簡體   English   中英

如何將這個javascript代碼重寫為C ++ 11?

[英]How can I rewrite this javascript code to C++11?

這是我在Javascript權威指南中看到的javascript閉包代碼。 我想把它寫成C ++ 11

var uniqueID1 = (function()
{
    var id = 0;
    return function() { return id++; };
})();    

這是我寫的cpp代碼。 但它沒有被編譯。 C ++ 11可以表示相同的表達式嗎?

auto c = []() -> int (*)() { int x = 0; return [&x]() -> int { return x++; }};

我正在使用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>

好的,首先讓我們分解你的JavaScript。

function()
{
    var id = 0;
    return function() { return id++; };
}

這創建了一個功能。 沒有名稱的函數,不帶參數。 調用此函數時,將返回一個新函數。 內部函數可以訪問本地范圍的變量,該變量將成為該內部函數狀態的一部分。

每次調用此函數時,它都將返回一個函數。 那個新函數將有自己的狀態( var id = 0;畢竟必須做一些事情)。 外部函數的每次調用都將返回一個具有新狀態的新函數。

這個:

(function()
{
    var id = 0;
    return function() { return id++; };
})

將函數包含在一對括號中。 這是運算符優先級規則所必需的,以允許它工作:

(function()
{
    var id = 0;
    return function() { return id++; };
})()

這將創建一個函數,然后調用該函數。 這就是最后()最后做的事情。 它調用外部函數,它創建一個具有自己范圍的內部函數並返回它。

在此表達式中,外部函數丟失 它消失了; 你不能再訪問它了。 你創建它的時間足夠長,可以調用它,然后讓它進入垃圾收集的垃圾桶。

鑒於所有這些,我們可以看到這句話:

var uniqueID1 = (function()
{
    var id = 0;
    return function() { return id++; };
})();

創建外部函數,調用返回新函數的函數,然后將內部函數存儲在名為uniqueID1的變量中。

如果您需要證明這是真的,請在HTML中嘗試:

var uniqueMaker = function()
{
    var id = 0;
    return function() { return id++; };
};

var uniqueID1 = uniqueMaker();
var uniqueID2 = uniqueMaker();

您將獲得與復制粘貼版本相同的答案。

如果我們希望C ++代碼模仿這一點,我們需要使用適當的C ++代碼執行每一步。

一,內在功能。 在C ++中,詞匯范圍不存在。 因此,您無法返回引用其他范圍中的變量的函數。 您只能返回一個具有來自另一個范圍的變量副本的lambda。 此外,除非您明確允許,否則lambdas無法修改范圍。 因此,內部代碼必須如下所示:

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創建外部函數,調用它,並存儲其返回值。 外部函數本身被丟棄。 所以我們需要模仿這個。 幸運的是,這在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()> 它不是外部函數的類型。 外部函數只是用於創建內部范圍的臨時函數。

我假設你不是要求字面翻譯,而是如何在C ++中最好地表達這個構造。 你的JavaScript構造在某種意義上是“假裝構造函數”,你的ID生成器最好用C ++表示為一個簡單的 然后你只需要創建該類的實例:

class UniqueID
{
    unsigned int value;
public:
    UniqueID() : value(0) { }
    unsigned int operator()() { return ++value; }
};

用法:

UniqueID gen1, gen2;

some_function(gen1());
another_function(gen2());
Foo x(Blue, "Jim", gen1());

這種方法比std::function包裝器重量輕,盡管直接lambda會產生類似的數據結構(盡管你不知道它的類型名稱)。 如果希望第一個ID為0,則可以將value初始化為-1 (盡管將0保留為特殊值可能很有用)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM