首頁 >後端開發 >C++ >為什麼編譯器對 Lambda 的最佳化比一般函數好?

為什麼編譯器對 Lambda 的最佳化比一般函數好?

Mary-Kate Olsen
Mary-Kate Olsen原創
2024-12-02 02:20:09184瀏覽

Why Do Compilers Optimize Lambdas Better Than Plain Functions?

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中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn