ラムダがプレーン関数と比較して強化されたコンパイラ最適化を可能にする理由
Nicolai Josuttis による C 標準ライブラリ (第 2 版) では、ラムダは次のことができると主張しています。単純な関数と比較して、コンパイラによってより効果的に最適化されます。この利点は、関数オブジェクトとしてのラムダの性質に由来します。
ラムダが関数テンプレートに渡されると、そのオブジェクトに合わせて特別に調整された新しい関数としてインスタンス化されます。これにより、コンパイラーはラムダ呼び出しを簡単にインライン化できるようになります。逆に、プレーン関数では、関数ポインタが関数テンプレートに渡されます。従来、コンパイラーは、関数ポインターを介して行われる呼び出しをインライン化するという困難に直面していました。
この概念を説明するために、次の関数テンプレートを考えてみましょう。
templatevoid map(Iter begin, Iter end, F f) { for (; begin != end; begin) *begin = f(*begin); }
ラムダを使用してこの関数を呼び出す:
int a[] = { 1, 2, 3, 4 }; map(begin(a), end(a), [](int n) { return n * 2; });
コンパイラによってインスタンス化が作成されます:
template void map(int* begin, int* end, _some_lambda_type f) { for (; begin != end; begin) *begin = f.operator()(*begin); }
この場合、コンパイラーは _some_lambda_type::operator() にアクセスでき、それに対する呼び出しをシームレスにインライン化できます。各ラムダには個別の型があるため、map() で異なるラムダを使用すると、新しいインスタンス化が生成されます。
ただし、代わりに関数ポインターが使用された場合:
map(int* begin, int* end, int (*f)(int)) { for (; begin != end; begin) *begin = f(*begin); }
コンパイラは、包括的な map() の呼び出しもインライン化され、特定の関数を正確に指定できるようになるまで、f への呼び出しをインライン化できません。これは、コンパイラの最適化という点で、プレーン関数よりもラムダの利点を強調しています。
免責事項: 提供されるすべてのリソースの一部はインターネットからのものです。お客様の著作権またはその他の権利および利益の侵害がある場合は、詳細な理由を説明し、著作権または権利および利益の証拠を提出して、電子メール [email protected] に送信してください。 できるだけ早く対応させていただきます。
Copyright© 2022 湘ICP备2022001581号-3