釋放 C++ 中 Lambda 表達式的強大威力
?Lambda 是 C++ 中的匿名函數(即沒有函數名的函數),可以在定義和使用時內聯。它們提供了一種方便的方式,將小的代碼塊作為參數傳遞給其他函數,或者在不需要創建命名函數的情況下定義一個函數。
?Lambda 在 C++ 中提供了一種靈活而簡潔的方式來編寫類似函數的對象,并在現代 C++ 編程中被廣泛使用。
Lambda 的定義使用以下語法:
捕獲列表(capture list)用于指定 lambda 中可訪問的來自外部作用域的變量。變量可以通過值捕獲、引用捕獲或使用 this 捕獲。
- 參數列表(argument list)指定將遞給 lambda 的參數。
- 返回類型(return type)指定 lambda 將返回的值的類型。如果未指定,則編譯器將嘗試推斷其類型。
- 函數體(function body)指定 lambda 被調用時將執行的代碼。
以下是在C++中使用 lambda 的幾種不同方式。
1、函數回調
函數回調是將一個函數作為參數傳遞給另一個函數,并在接收函數稍后的時間調用該函數。您可以將 lambda 作為函數參數傳遞,其中它將在發生某個事件時執行。
示例:
在這個例子中,sum 變量是一個Lambda表達式,它接受兩個參數 a 和 b,并返回它們的總和。std::accumulate 函數接受數字向量、結果的初始值和 sum 函數(Lambda 表達式)。該函數計算向量中所有元素的總和并返回結果,該結果被打印在屏幕上。
另一個例子:
在這種情況下,lambda 表達式 [&sum](int x) { sum += x; } 被傳遞作為要應用于每個元素的函數。lambda 通過引用 & 捕獲變量 sum,以便可以在 lambda 主體中進行修改。
兩個例子都達到了相同的結果,但第二個例子使用了 std::for_each 算法和 lambda 表達式,這是在 C++ 中更現代、更簡潔的技術。
2、默認捕獲
當一個 lambda 表達式被聲明時沒有任何顯式的捕獲,其默認行為是通過引用捕獲周圍作用域中的變量。這被稱為默認捕獲。
例子:
在第二個例子中,定義了一個 lambda 表達式并將其存儲在名為 square 的變量中。這個 lambda 表達式接受一個 int 類型的參數 x,并返回 x * x 的值,即參數的平方。
在主函數中,這個 lambda 表達式被用作函數對象。通過傳遞一個值為 5 的參數來調用它,并使用 cout 流顯示結果。
3、按值捕獲
這是 lambda 表達式的最簡單形式,其中你通過值傳遞變量給函數。當一個變量被按值捕獲時,它的當前值被存儲在閉包中,而當周圍作用域中的變量發生改變時,它的值不會被更新。這可以通過將變量包含在方括號 [ ] 中來實現。
例子:
4、按引用捕獲
你可以通過使用 & 符號將變量傳遞給 lambda 表達式來按引用捕獲變量。當一個變量被按引用捕獲時,它的當前值被存儲在閉包中,并且在周圍作用域中變量發生變化時被更新。這是通過在方括號[ ]中在變量前加上取地址運算符 & 來實現的。
例子:
5、可變Lambda表達式
默認情況下,由 lambda 表達式捕獲的變量是常量,不能在 lambda 表達式體內修改。如果你想要在 lambda 表達式中修改捕獲的變量,你可以將 lambda 表達式設為可變。可變lambda允許捕獲的變量被修改。這是通過在方括號 [ ] 中包含可變關鍵字來實現的。
例子:
lambda 表達式類似于普通函數,但它們有一些關鍵的區別。例如,lambda 表達式的類型沒有被顯式指定,但可以由編譯器推斷出來。此外,lambda 表達式可以從周圍的作用域中捕獲變量,這使得它們非常適用于創建閉包和在 C++ 中使用函數式編程概念。
與傳統函數相比,lambda 表達式具有一些性能優勢:
- 內聯函數:編譯器會自動將 lambda 表達式內聯,這意味著它們的代碼直接插入到調用函數中。這可以減少函數調用的開銷并提高性能。
- 避免命名函數的開銷:lambda 表達式沒有名稱,因此它們不必被聲明和存儲在符號表中,這可以減少開銷并提高性能。
- 改善高速緩存局部性:lambda 表達式可以在同一個函數中定義和使用,這意味著lambda使用的代碼和數據將存儲在與調用代碼相同的高速緩存行中。這可以改善高速緩存局部性并降低高速緩存失效的成本。
- 減小代碼大小:lambda 表達式通常比命名函數小,并且它們不需要外部函數調用,這可以減小編譯代碼的大小并提高性能。
- 增加靈活性:lambda 表達式可以用來將函數作為參數傳遞給其他函數,這提供了更大的靈活性,可以改善性能,減少重復代碼的需求。
- 提高可讀性:lambda 表達式可以通過以緊湊而自包含的方式封裝復雜的邏輯來使代碼更易于閱讀。這可以通過使代碼更易于理解和維護來提高性能。
總之,與傳統函數相比,lambdas 可以通過減少開銷、提高緩存位置、減少代碼大小、提高靈活性和提高可讀性來提高性能。