C ++ 11クロージャーについて正しく考える方法とstd::function
、それらがどのように実装され、メモリーがどのように処理されるかという点について、いくつかの情報が欲しいのですが。
私は時期尚早の最適化を信じていませんが、私は新しいコードを書くときに自分の選択がパフォーマンスに与える影響を慎重に検討する習慣があります。また、マイクロコントローラーやオーディオシステムなど、非決定的なメモリ割り当て/割り当て解除の一時停止を回避するために、かなりの量のリアルタイムプログラミングを行っています。
したがって、C ++ラムダをいつ使用するか、または使用しないかについての理解を深めたいと思います。
私の現在の理解では、キャプチャされたクロージャのないラムダは、Cコールバックとまったく同じです。ただし、環境が値または参照によってキャプチャされると、匿名オブジェクトがスタックに作成されます。関数から値のクロージャを返す必要がある場合は、それをでラップしstd::function
ます。この場合、クロージャメモリはどうなりますか?スタックからヒープにコピーされますか?が解放されるたびに解放されますか?std::function
つまり、aのように参照カウントされstd::shared_ptr
ますか?
リアルタイムシステムでラムダ関数のチェーンをセットアップし、Bを継続引数としてAに渡して、処理パイプラインA->B
が作成されると思います。この場合、AクロージャーとBクロージャーは一度割り当てられます。これらがスタックとヒープのどちらに割り当てられるかはわかりませんが。ただし、一般的に、これはリアルタイムシステムで安全に使用できます。一方、Bがラムダ関数Cを作成してそれが返す場合、Cのメモリは繰り返し割り当てと割り当て解除が行われ、リアルタイムの使用には受け入れられません。
疑似コードでは、DSPループはリアルタイムで安全になると思います。ブロックAを処理してからBを処理したいのですが、Aは引数を呼び出します。これらの関数は両方ともstd::function
オブジェクトを返すのでf
、std::function
オブジェクトは、環境がヒープに格納されます。
auto f = A(B); // A returns a function which calls B
// Memory for the function returned by A is on the heap?
// Note that A and B may maintain a state
// via mutable value-closure!
for (t=0; t<1000; t++) {
y = f(t)
}
そして、私がリアルタイムコードで使うのが悪いと思うもの:
for (t=0; t<1000; t++) {
y = A(B)(t);
}
そして、スタックメモリがクロージャに使用されている可能性が高いと私が考える1つ:
freq = 220;
A = 2;
for (t=0; t<1000; t++) {
y = [=](int t){ return sin(t*freq)*A; }
}
後者の場合、クロージャーはループの反復ごとに作成されますが、前の例とは異なり、関数呼び出しのように安価なので、ヒープの割り当ては行われません。さらに、コンパイラーがクロージャーを「持ち上げ」、インライン最適化を行うことができるのかと思います。
これは正しいです?ありがとうございました。
operator()
ます。実行する「リフティング」はありません。ラムダは特別なものではありません。これらはローカル関数オブジェクトの省略形にすぎません。