首頁 > 後端開發 > C++ > 編譯器可以比普通函數更好地最佳化 Lambda 嗎?

編譯器可以比普通函數更好地最佳化 Lambda 嗎?

Mary-Kate Olsen
發布: 2024-11-19 18:33:03
原創
237 人瀏覽過

Can Lambdas Be Optimized Better Than Plain Functions By Compilers?

Lambda 與普通函​​數的編譯器優化

Nicolai Josuttis 在他的書《C 標準庫(第二版)》中聲稱編譯器可以比普通函數更好地最佳化lambda。考慮到 lambda 表達式和普通函數都可以內聯,這似乎有悖常理。但是,兩者之間存在細微差別,可以在 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 的operator() 以及對其進行簡單的內聯呼叫。

但是當用函數指標呼叫時:

map(begin(a), end(a), &multiply_by_two);
登入後複製

實例化變成:

template <>
void map<int*, int (*)(int)>(int* begin, int* end, int (*f)(int)) {
    for (; begin != end; ++begin)
        *begin = f(*begin);
}
登入後複製

這裡,每次呼叫map時f都會引用不同的函數,防止編譯器不會進行內聯調用,除非map 本身是內聯的。

結論

作為函數物件的 lambda 的獨特類型使編譯器能夠創建特定的函數實例化並無縫內聯其調用。這種增強的最佳化功能將 lambda 與普通函​​數區分開來,使它們成為提高程式碼效能和效率的首選。

以上是編譯器可以比普通函數更好地最佳化 Lambda 嗎?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板