std::function を const 参照で渡す必要がありますか? 質問する

std::function を const 参照で渡す必要がありますか? 質問する

次のような関数があるとしますstd::function:

void callFunction(std::function<void()> x)
{
    x();
}

x代わりに const-reference で渡す必要がありますか?

void callFunction(const std::function<void()>& x)
{
    x();
}

std::functionこの質問に対する答えは、関数がそれに対して何を行うかによって変わりますか? たとえば、データ メンバーに格納または初期化するメンバー関数またはコンストラクターの場合です。

ベストアンサー1

パフォーマンスが必要な場合は、値を保存するときに値を渡します。

「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そこからが構築され、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) では、 を長期ストレージにコピーするだけです。ケース (B) では、 をコピーする必要がありmoveます。std::functionstd::function

そのストアにより、値渡しがより最適になります。 のコピーを格納している可能性がある場合は、std::function値渡しします。それ以外の場合は、どちらの方法もほぼ同等です。値渡しの唯一の欠点は、同じかさばる を取得しstd::function、サブメソッドが次々に使用する場合です。それ以外の場合は、 はmoveと同じくらい効率的ですconst&

さて、 内に永続的な状態がある場合に主に発生する、2 つの違いは他にもいくつかありますstd::function

std::functionが を持つオブジェクトを格納しているoperator() constが、変更するデータ メンバーもいくつかあると仮定しますmutable(失礼ですね)。

このstd::function<> const&場合、mutable変更されたデータ メンバーは関数呼び出しの外に伝播します。 このstd::function<>場合、伝播しません。

これは比較的奇妙なコーナーケースです。

std::function他の重量があり、安価に移動可能なタイプと同じように扱う必要があります。移動は安価ですが、コピーは高価になる可能性があります。

おすすめ記事