2010-12-12 6 views
4

いくつかの状況で値や参照のセマンティクスを選択するかどうかについての感情(私は願っています)はありません。私が適用できる大まかなルールはありますか?この場合の値または参照のセマンティクス?

私は通常、組み込みデータ型(char、int、bool、doubleなど)以外のすべての参照を選択します。しかし、関数から参照を返すことができないことがあるので、ポインタを使用する必要があります。次の関数は、この例です:

Foo bar() 
{ 
    Foo f; 
    f.do_stuff(); 
    return f; 
} 

私はFooのオブジェクトを格納するために、ブースト:: shared_ptrのを使用したいが、それは非常に醜いオブジェクトでの作業になります。私は現在、10以上の要素を持つことはほとんどないデッキを返す関数を見ています(これは私が想定しているものです、私は確かめる方法がありません)。これを価値によって戻すことは間違いないでしょうか?私の考察は早すぎる最適化のケースですか?

+0

の可能重複[C++の関数にオブジェクトを渡す方法?](http://stackoverflow.com/questions/2139224/how-to-pass-objects-to-functions-in-c) – fredoverflow

答えて

3

ほとんどのコンパイラは余分なコピーを最適化するため、値を返すことは問題ありません(これは、戻り値の最適化、またはあなたの場合は名前付き戻り値の最適化と呼ばれます)。

しかし、慣用的な方法は、あなたはいつもこれを行うことができ

void bar(Foo& out) 
{ 
    out.do_stuff(); 
} 
+2

@fhd:しかし、このアプローチには2つの欠点があります。あなたが望む状態に 'out'があることを確認しなければならず、入力するのが面倒です(自然ではありません)。私は通常、価値あるものに戻り、NRVOに頼っています。 –

+0

@fhd:ただし、このアプローチでは利点があります。つまり、関数内でオブジェクトを構築しないため、例外の安全性を損なう可能性のある構築上の失敗を取り除くことができます。 –

+0

妥当な音、ありがとう! – Neo

3

いずれにしても、を返すことはありません。参照またはポインタによってスタックに割り当てられたもの(ここではfなどのローカル変数)。

+0

どうして ? (文字制限..) –

+1

@Alex:スタックに割り当てられているので、関数がスタックベースの変数の割り当てが解除され、ポインタまたは参照が無効になるときに返されるためです。 – sashang

+0

@sashang:言葉遣いが不明確(さらには間違っている)。それは "何も返さない..."でなければなりません。私はdownvoteを与え、@Ofirがその答えを編集することを提供するdownvoteを取り消します。 –

0

です:

Foo& bar(Foo& f) 
{ 
    f.do_stuff(); 
    return f; 
} 

をそして、このようにそれを使用します。ここでの欠点は、あなたができることです

Foo f; 
bar(f); 

bar()Fooオブジェクトの新しいコピーを受け取ることを保証しません。重要な場合は、次のように変更する必要があります。

ただし、新しいコピーが作成された場合は不要な初期化が行われます。あるいは、doSomething()の前にfを調べて、期待通りでない場合は例外をスローすることもできます。

0

任意の変数またはオブジェクトの状態を維持する場合(つまり、呼び出されたルーチンによって変数/オブジェクトに対して何らかの処理が行われた後に、同じ変数を呼び出し側ルーチンにリターンする場合)、また大きいデータを関数に渡すと、大きなボリュームデータの二重コピーがあります。

また、オブジェクトのビット単位のコピーを防止する必要がある場合、そのような場合には、クラスのコピーコンストラクタを非公開にします。

-1

私の通常のルールは以下のとおりです。

  1. は常に値でパスを使用します。

    シンプルなのですか?参照吸う。彼らは決して導入されてはいけません。

  2. "値のようなデータ構造"がある場合は、それを渡します。あなたが "データ構造のようなオブジェクト"を持っているなら、ポインタを渡します(参照セマンティクス、値渡し)。

    通常、どのような種類のものが値かオブジェクトかはっきりしています。それを突然変異させることができれば、そのオブジェクトです。

関連する問題