2013-07-24 11 views
8

I再帰的なラムダの実装に興味を持って、そしてフィボナッチ計算のために、このコードが見つかりました:再帰的なラムダimplemention ++ 11

std::function<int(int)> lfib = [&lfib](int n) {return n < 2 ? 1 : lfib(n-1) + lfib(n-2);}; 

そして、私は疑問を持っているが:/ std::functionは、多型の機能であるので、lfibが作成をし、ラムダをスタックではなくヒープメモリに保存します。したがって、は、プログラムのの最適化の可能性を失うことがあります。正しいかどうか?

+4

はい。いいえ。 –

+8

O(2^N)アルゴリズムの複雑さを持つプログラムに対して、関数呼び出しの仕組みは重要ではありません。 – Cubbi

+0

私はfibbonachiの実装について尋ねていない、私はstdについて尋ねられました::機能は、プログラムの損失を最適化する可能性があります。 –

答えて

5

std::functionの状態であるタイプ消去データは、おそらくヒープ割り当てによってstd::functionまたはそのコピーが存在する限り持続します。

同じことが、キャプチャされた変数を含むクロージャには当てはまりません。これはラムダオブジェクトの状態の一部であり、おそらく現在の関数が返って変数lfibが有効範囲外になると消えるスタック上のデータ構造のアドレスを含んでいます。

参考としてlfibをキャプチャしたことに注意してください。したがって、関数の残りの部分に対するlfibへの変更は、ラムダから見えるようにする必要があります(初期化を含むがこれに限定されない)。コンパイラが一般的な方法でそれを管理できる唯一の方法は、ローカルlfibのアドレスを格納することです。特殊なケースでは、lfibが再度割り当てられない場合、コンパイラーは参照の代わりに初期化直後の値を格納する可能性があります。しかし、それは保証されておらず、特にそうではありません。

+1

このような小さなラムダは、おそらくSmall Buffer最適化であり、ヒープ割り当てを引き起こしません。 – Xeo

+0

@尾根:おそらく。私は 'std :: function'実装の専門家ではありません。ここで興味深いのは生涯です。 –

+0

@Xeo:libstdC++ではなく、何らかの理由でlambdasが 'std :: function'自体に直接格納されることはありません。なぜなら、それらは"位置不変 "とはみなされないからです。 'std :: _ Function_base :: _ Base_manager :: __ stored_locally'を参照してください。 – Fanael