4

std::async標準のスレッドメカニズムを使用できないプログラムがあります。代わりに、次のようにプログラムをコーディングする必要があります。

void processor( int argument, std::function<void(int)> callback ) {
  int blub = 0;

  std::shared_ptr<object> objptr = getObject();

  // Function is called later.
  // All the internal references are bound here!
  auto func = [=, &blub]() {
    // !This will fail since blub is accessed by reference!
    blub *= 2;

    // Since objptr is copied by value it works.
    // objptr holds the value of getObject().
    objptr->addSomething(blub);

    // Finally we need to call another callback to return a value
    callback(blub);
  };

  objptr = getAnotherObject();

  // Puts func onto a queue and returns immediately.
  // func is executed later.
  startProcessing(func);
}

私は今、それを正しく行っているかどうか、またはラムダを非同期コールバックとして使用する最良の方法は何かを知りたいと思います。

編集:コードコメントに期待される動作を追加しました。の問題の可能な解決策については、回答/コメントを参照してくださいblub

4

1 に答える 1

4

関数オブジェクトには、ローカル変数への参照が含まれますblub言語の他のすべての状況と同様に、これにより、関数の終了後にローカル変数が有効になりません。

他のすべてのキャプチャされたオブジェクトのコピーは、値によってキャプチャされるため、関数オブジェクト内に格納されます。これは、それらに問題がないことを意味します。

関数が終了した後も存続させたい場合、その寿命を関数に結びつけることはできません。動的ストレージ期間が必要です。Astd::unique_ptrを使用してそのようなオブジェクトのクリーンアップを処理できますが、ラムダに「移動ごとにキャプチャ」できないため、少し面倒です:S

auto blub = make_unique<int>(0); // [1]

std::shared_ptr<object> objptr = getObject();

// use std::bind to store the unique_ptr with the lambda
auto func = std::bind([=](std::unique_ptr<int>& blub) {
  *blub *= 2;

  objptr->addSomething(*blub);

  callback(*blub);
}, std::move(blub)); // move the unique_ptr into the function object

objptr = getAnotherObject();

// func is not copiable because it holds a unique_ptr
startProcessing(std::move(func)); // move it

追加のメモとして、ラムダが値によってそれをキャプチャするとコピーされ、その奇妙なコピーセマンティクスがまさに必要なものであるため、古い非推奨std::auto_ptrは実際にはここでうまく機能します。


1. については、 GOTW #102を参照してくださいmake_unique

于 2012-04-27T21:18:29.713 に答える