2011-12-20 5 views
1

私のプロジェクトには、プロデューサとコンシューマという2つのコンポーネントがあります。プロデューサは、いくつかの情報を処理し、その結果を消費者に与える責任がある。結果は関数オブジェクトの助けを借りて渡されます。std :: functionが使用されたときの余分なコピーコンストラクタ

私はこの情報を渡すための関数を使用しています。あなたはそれが下のコードでどのように見えるかを見ることができます。

#include <iostream> 
#include <vector> 
#include <functional> 

using namespace std; 

class Data { 
    std::vector<int> vec; 
public: 
    Data() { 
     cout << "Data()" << endl; 
    } 

    Data(const Data& rr) : vec(rr.vec) { 
     cout << "Data(Data&)" << endl; 
    } 

    ~Data() { 
     cout << "~Data()" << endl; 
    } 

    Data(Data&& rr) : vec(move(rr.vec)) { 
     cout << "Data(Data&&)" << endl; 
    } 

    void get() { 
    } 
}; 

class Producer { 
public: 
    void process(function<void(Data)> f) { 
     Data data; 
     f(move(data)); 
    } 

    void process2(void(&pf)(Data)) { 
     Data c; 
     pf(move(c)); 
    } 

}; 

void Consume(Data a) { 
    cout << "Consume(data)" << endl; 
} 

int main() { 
    { 
     cout << "use function() " << endl; 
     Producer p; 
     p.process([](Data a) { 
      cout << "Consume(data)" << endl; 
     }); 
    } 

    { 
     cout << endl; 
     cout << "use function pointer" << endl; 
     Producer p;; 
     p.process2(Consume); 
    } 
    return 0; 
} 

それは関数オブジェクトを使用する場合、追加のコピーコンストラクタがありますが、次の出力

use function() 
    Data() 
    Data(Data&&) 
    Data(Data&) 
    Data(Data&) 
    Consume(data) 
    ~Data() 
    ~Data() 
    ~Data() 
    ~Data() 

    use function pointer 
    Data() 
    Data(Data&&) 
    Consume(data) 
    ~Data() 
    ~Data() 

を持っています。

私は間違っていましたか?これらの余分なコンストラクタを取り除くことは可能ですか?

ありがとうございます。

私はVC10 SP1を使用しています。

+0

g ++では、移動コンストラクタを3回呼び出すだけです。 – kennytm

+0

'std :: function'は大きくて高価です...良いコンパイラの最適化ができればうれしいですが、' std :: function'が提供する膨大な柔軟性を考えれば、どれくらい最適化できるかには限界があります。クランチでは、パフォーマンスが重要なときに 'std :: function'への明示的な変換よりも関数ポインタや' auto'/lambdaを優先します。 –

+5

MSVC11で修正されます。私の答えはこちらをご覧ください:http://stackoverflow.com/questions/8203211/how-can-i-make-the-storage-of-c-lambda-objects-more-efficient/8205037#8205037 –

答えて

0

ここにはいくつかのオプションがあります。

  • std::functionを使用しないでください、あなたの非キャプチャラムダは、あなたの関数テンプレートを作成し、std::functionを使用しないでくださいvoid(*)(Data)
  • に変換され、コンパイラはラムダの隠されたタイプを推測することができます。
  • オブジェクトをコピーしたり、ポインタや参照として渡したりしないでください。プログラムのフルバージョンが何をしているかによって、ヒープに割り当ててstd::unique_ptrを使用する方が効率的です。
関連する問題