パフォーマンスが必要な場合は、格納する場合は値で渡します。
「これをUIスレッドで実行する」という関数があるとします。
std::future<void> run_in_ui_thread( std::function<void()> )
「ui」スレッドでいくつかのコードを実行しfuture、完了時にを通知します。(UIスレッドがUI要素をいじるはずの場所にあるUIフレームワークで役立ちます)
検討しているシグネチャは2つあります。
std::future<void> run_in_ui_thread( std::function<void()> ) // (A)
std::future<void> run_in_ui_thread( std::function<void()> const& ) // (B)
現在、これらを次のように使用する可能性があります。
run_in_ui_thread( [=]{
// code goes here
} ).wait();
これは匿名のクロージャー(ラムダ)を作成std::functionし、それからoutを作成し、それをrun_in_ui_thread関数に渡し、メインスレッドで実行が完了するのを待ちます。
(A)の場合、std::functionはラムダから直接作成され、内で使用されますrun_in_ui_thread。ラムダはにmove組み込まれているstd::functionので、あらゆる可動状態が効率的にそこに運ばれます。
2番目のケースでは、一時的な std::functionが作成され、ラムダがmoveそれに挿入され、そのテンポラリstd::functionが内で参照によって使用されますrun_in_ui_thread。
これまでのところ、非常に優れています。2つは同じように動作します。を除いて、run_in_ui_thread実行するためにuiスレッドに送信する関数引数のコピーを作成します!(処理が完了する前に戻るため、参照を使用することはできません)。ケース(A)の場合、単純にmovestd::functionその長期保存に。ケース(B)では、をコピーする必要がありstd::functionます。
そのストアは、値による受け渡しをより最適にします。のコピーを保存している可能性がある場合はstd::function、値で渡します。それ以外の場合、どちらの方法もほぼ同じです。値渡しの唯一の欠点は、同じかさばるstd::function、サブメソッドを次々に使用する場合です。それを除けば、aはとmove同じくらい効率的const&です。
さて、2つの間には他にもいくつかの違いがあります。これらの違いは、内に永続的な状態がある場合に主に発生しstd::functionます。
は、std::functionいくつかのオブジェクトをで保存するとしますが、変更するデータメンバーoperator() constもいくつか持っているものとしmutableます(失礼です)。
このstd::function<> const&場合、mutable変更されたデータメンバーは関数呼び出しから伝達されます。そのstd::function<>場合、彼らはしません。
これは比較的奇妙なコーナーケースです。
あなたstd::functionは、他のおそらくヘビー級の安価な可動タイプと同じように扱いたいです。移動は安く、コピーは高価になる可能性があります。
sizeof(std::function)以上ないことを期待します2 * sizeof(size_t)。