Lambda 最佳化和內聯函數:編譯器的優勢
Nicolai Josuttis 的說法(與普通函數相比,lambda 表現出卓越的編譯器優化)引起了許多人的興趣開發人員。透過調查這項說法,我們試圖揭示這種優化優勢背後的根本原因。
函數物件和內聯
作為函數物件的Lambda 擁有一個關鍵優勢:將它們傳遞給函數模板會觸發專門為該lambda 定制的函數的實例化。這允許編譯器毫不費力地內聯 lambda 調用。
相反,函數在傳遞給函數模板時使用函數指標。傳統上,編譯器在透過函數指標內聯呼叫時遇到挑戰。只有當封閉函數本身內聯時,內聯最佳化才是可行的。
模板實例化:探索差異
為了說明這種差異,請考慮映射函數模板:
template <typename Iter, typename F> void map(Iter begin, Iter end, F f) { for (; begin != end; ++begin) *begin = f(*begin); }
使用lambda 呼叫它:
int a[] = { 1, 2, 3, 4 }; map(begin(a), end(a), [](int n) { return n * 2; });
會產生自訂實例化:
template <> void map<int*, _some_lambda_type>(int* begin, int* end, _some_lambda_type f) { for (; begin != end; ++begin) *begin = f.operator()(*begin); }
編譯器辨識_some_lambda_type::operator() 函式並且可以直接內聯呼叫它。每個不同的 lambda 類型都會提示映射的新實例化,從而保證特定於 lambda 的最佳化。
相反,使用函數指標呼叫 map 會產生以下實例化:
template <> void map<int*, int (*)(int)>(int* begin, int* end, int (*f)(int)) { for (; begin != end; ++begin) *begin = f(*begin); }
這裡,函數指標 f 指向每個映射呼叫的不同位址,從而禁止內聯最佳化。必須內聯對 map 的調用,編譯器才能將 f 解析為特定函數。
因此,lambda 作為函數物件的獨特性及其促進模板實例化的能力使編譯器具有比傳統函數呼叫更強的最佳化能力通過指標。
以上是為什麼編譯器優化 lambda 函數比傳統函數更有效?的詳細內容。更多資訊請關注PHP中文網其他相關文章!