[英]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.