起因
做遊戲開發多少會接觸lua,其中閉包也是挺常見的一種了,因爲使用lua閉包的緣故,我就嘗試着在C++使用lambda來寫個。
代碼分析
以下是lua的閉包代碼:
function fun1(param1)
local i = param1
return function()
i = i + 1
return i
end
end
local test1 = fun1(1)
local test2 = fun1(1)
print("test1_1...." .. test1())
print("test1_2...." .. test1())
print("test2_1...." .. test2())
print("test2_2...." .. test2())
如果對閉包不瞭解來看看輸出結果如何?
現在知道結果了,讓我們來分析分析這段代碼吧!
已經瞭解閉包的小夥伴可以跳過這段
從輸出上分析: test1與test2的值可以看出是互不影響的,並且同一個test1執行多次後值是疊加的,說明這個i並沒有像我們寫C++時候函數執行完就銷燬。爲了簡單的比喻,在看到閉包時,你可以把他想象成一個類,並結合閉包結構分析,可以想成如下:
class fun1()
{
public:
fun1(int _i) : i(_i) {}
int GetAddOneNum()
{
return ++i;
}
private:
int i;
}
我們將上面lua代碼比作先創建一個 fun1 類對象 test1,而 test1() 則比作爲 test1.GetAddOneNum();,是不是就好像剛剛閉包的執行結果了?如果覺得不太形象你可以嘗試着吧GetAddOneNum改寫爲重載 () 這個運算符。
閉包則是一個函數在帶上了狀態,讓這個函數有了自己的變量如剛剛的 i 變量。
我們按照lua的模板來寫一個C++代碼。
return function() i = i + 1 return i end
返回的不就是一個函數嗎,那我們C++中使用lambda就行了,而有個問題是變量,我們在C++中並不能像lua那樣,我們執行完 fun() 函數後 i 就被銷燬了,所以改下成了如下代碼,動態的給他分配內存,防止內存管理上的問題不用猶豫用智能指針。
以下是改裝後的C++代碼:
auto fun(int _i)
{
shared_ptr<int> i = make_shared<int>(_i);
return [=]() -> int {
*i += 1;
return *i;
};
}
int main()
{
auto test1 = fun(1);
auto test2 = fun(100);
std::cout << "test1_1..." << test1() << std::endl;
std::cout << "test1_2..." << test1() << std::endl;
std::cout << "test2_1..." << test2() << std::endl;
std::cout << "test2_2..." << test2() << std::endl;
return 0;
}
看看執行結果吧?
實驗得真知,從結果上可以看出方法是可行的,而這段C++代碼我就不解釋了,跟上面差不多的。