ホームページ > バックエンド開発 > C++ > コンパイラが単純な関数よりもラムダを最適化するのはなぜですか?

コンパイラが単純な関数よりもラムダを最適化するのはなぜですか?

Mary-Kate Olsen
リリース: 2024-12-02 02:20:09
オリジナル
179 人が閲覧しました

Why Do Compilers Optimize Lambdas Better Than Plain Functions?

ラムダ関数の最適化

Nicolai Josuttis は、「The C Standard Library」の中で、コンパイラーは単純な関数よりもラムダを最適化すると主張しています。これは、なぜそうなるのかという疑問を引き起こします。

インライン最適化

インライン最適化ではラムダ関数とプレーン関数が区別されないと考える人もいるかもしれません。ただし、重要な違いは、関数オブジェクトとしてのラムダの性質にあります。

関数オブジェクトと関数ポインター

ラムダが関数テンプレートに渡されると、は、そのオブジェクト専用の新しい関数を作成し、その結果、簡単にインライン化可能な関数呼び出しが行われます。対照的に、プレーン関数は関数ポインターを渡すため、通常はインライン最適化で問題が発生します。コンパイラは理論的にはそのような呼び出しをインライン化できますが、それは周囲の関数もインライン化されている場合に限られます。

イテレータと関数オブジェクトを次のように受け取る関数テンプレート マップを考えてみましょう。パラメータ:

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);
}
ログイン後にコピー

コンパイラはラムダの演算子()への呼び出しを簡単にインライン化できます。

ただし、関数ポインタを使用する:

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 はマップの呼び出しごとに異なるアドレスを指し、周囲のマップの呼び出しもインライン化されない限りインライン最適化を禁止します。

したがって、次の最適化の利点は次のようになります。ラムダは、簡単なインライン機能を可能にする関数オブジェクトを作成する機能に由来しています。

以上がコンパイラが単純な関数よりもラムダを最適化するのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート