2012-08-03 12 views
7

私はクラスの移動セマンティクスの実装にかなりの時間を費やしましたが、今はそれを使用する関数を扱っています。セマンティクスとconst参照を移動する

私は移動のセマンティクス(コンストラクタと演算子=)を実装したヒープ上に多くのデータを持つこのオブジェクトを持っています。CLargeObそれは、オブジェクトがゴミ箱に移動/移動することができるように、常に可能ではありませんので、私はこの2つの機能を追加しましたしかし

void OtherOb::Func(CLargeOb&& largeOb1, CLargeOb&& largeOb2) 
{ 
    SomeOtherFunc(largeOb1); // use objects 
    SomeOtherFunc(largeOb2); 
    m_largeOb1 = (CLargeOb&&)largeOb1; // save as members and trash the originals 
    m_largeOb2 = (CLargeOb&&)largeOb2; 
} 

void OtherOb::Func(const CLargeOb& largeOb1, CLargeOb&& largeOb2) 
{ 
    SomeOtherFunc(largeOb1); 
    SomeOtherFunc(largeOb2); 
    m_largeOb1 = largeOb1; 
    m_largeOb2 = (CLargeOb&&)largeOb2; 
} 

void OtherOb::Func(CLargeOb&& largeOb1, const CLargeOb& largeOb2) 
{ 
    SomeOtherFunc(largeOb1); 
    SomeOtherFunc(largeOb2); 
    m_largeOb1 = (CLargeOb&&)largeOb1; 
    m_largeOb2 = largeOb2; 
} 

それは動作しますが、あなたはすでにできることが理想的にこのように使用されます私がこれらのオブジェクトの3つ以上をパラメータとして取る機能を持っていると、* ssの大きな痛みになるだろうと推測します。テンプレートを使用してこれを解決する巧妙な方法はないでしょうか?

+0

@MooingDuck:VS2010で問題なく動作します。演算子=(&&)を呼び出すには、std :: moveまたは&& castを使用して明示的に呼び出す必要があります。しかし、そのソリューションはそれよりはるかに優れています。 – demorge

+0

@demorge:ああ、私は名前が付けられたときにルールの変更を完全に忘れてしまった。申し訳ありません –

+1

'(CLargeOb &&)largeOb1'ではなく' std :: move(largeOb1) 'と書いてください。プログラマーの世代は、標準ではなく、慣用で境界のない読み取り不可能なC/C++ミックスの代わりに、ムーブを可能にする標準的なC++ 11の方法を使用してくれてありがとう。 – fredoverflow

答えて

15

C++ 03の場合と同様に、ガイドラインはです。コピーが必要な場合は、パラメータリストに作成してください。これは、いくつかの専門的な過負荷と同じくらい効率的である

OtherOb o; 

CLargeOb x, y; 
const CLargeOb z; 

o.Func(x, std::move(y)); // need x for later, done with y so move it 
o.Func(std::move(x), z); // done with x, necessarily copy z 

void OtherOb::Func(CLargeOb largeOb1, CLargeOb largeOb2) 
{ 
    SomeOtherFunc(largeOb1); // use objects 
    SomeOtherFunc(largeOb2); 
    m_largeOb1 = std::move(largeOb1); // save as members and trash the originals 
    m_largeOb2 = std::move(largeOb2); // (you should use std::move, not cast) 
} 

、発信者:

これは、オブジェクトを取得する方法と、呼び出し元の契約をすることができます、あなただけに関係なく、オブジェクトを取得します。どうして? これらはすでにコンストラクタとしてクラスに存在するため、です。コンパイラがあなたのためにコールサイトで呼び出すべきものを把握させると、それはすでに何をすべきかを知っています。

+2

私はそれをとても愛し、とても簡単です! – demorge

+0

これは1回ではなく2回移動しませんか? (注:もちろん、1つの追加の動きはほとんど気にならないはずですので、私はとにかくupvotedしました) – Sjoerd

+0

@Sjoerd:はい、コンパイラはどこかで動きをなくすことができます。たとえそれがなくても、それは問題ではありません。 – GManNickG

関連する問題