10

私のコード:

#include <iostream>
#include <functional>
using namespace std;

struct A {
  A() = default;
  A(const A&) {
    cout << "copied A" << endl;
  }
};

void foo(A a) {}

int main(int argc, const char * argv[]) {
  std::function<void(A)> f = &foo;
  A a;
  f(a);
  return 0;
}

コンソールに「コピーされた A」が 2 回表示されます。オブジェクトが 1 回ではなく 2 回コピーされるのはなぜですか? どうすればこれを適切に防ぐことができますか?

4

2 に答える 2

10

特殊std::function<R(Args...)>化には、次の宣言を持つ呼び出し演算子があります。

R operator()(Args...) const;

あなたの場合、これはオペレーターがA. そのf(a)ため、値渡しのセマンティクスにより、呼び出しの結果はコピーになります。ただし、基になるfooターゲットもその引数を値で受け入れます。したがって、パラメータfが に転送されると、2 番目のコピーが作成されfooます。

これは設計によるものであり、実際にAは、移動コンストラクターがあった場合、コピーが 1 つしかなく、その後に移動構築が続きます。呼び出しにより、移動構築f(std::move(a))は 2 つだけになります。2 つのコピーが多すぎると感じた場合は、 eg の代わりにと の両方fooを使用するf必要があるかどうか、および/または賢明な移動コンストラクターを使用できるかどうかを再検討する必要があります。AA const&A

std::function<void(A const&)> f = &foo;変更せずに行うこともできますfoo。ただし、変更fooが制御できない場合、および/またはA安価な移動を構築可能にすることがオプションではない場合に備えて、それを予約する必要があります。C++11 での値渡しは何も問題がないので、両方とも を使用するか、両方を使用することをお勧めしAますA const&

于 2012-08-10T15:33:29.937 に答える
1

値で渡すため、コピーされています。代わりに const 参照として渡すことで、すべてのコピーを回避できます。

于 2012-08-10T15:17:20.653 に答える