Lambda 函數最佳化
Nicolai Josuttis 在《C 標準庫》中聲稱,編譯器對 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); }
編譯器可以輕鬆內聯調用lambda 的運算子()。
但是,當使用函數指標:
int a[] = { 1, 2, 3, 4 }; map(begin(a), end(a), &my_function);
結果實例化變成:
template <> void map<int*, int (*)(int)>(int* begin, int* end, int (*f)(int)) { for (; begin != end; ++begin) *begin = f(*begin); }
這裡,f對於每次對map的呼叫都指向不同的位址,禁止內聯優化,除非周圍對map的呼叫也內聯。
因此,最佳化優勢lambda 源自於它們建立函數物件的能力,這些函數物件支援簡單的內聯功能。
以上是為什麼編譯器對 Lambda 的最佳化比一般函數好?的詳細內容。更多資訊請關注PHP中文網其他相關文章!