2013-10-16 8 views
6

への参照を返す...C++は、私がこれに似た質問がある知っているが、それらのどれも私の質問に明確な答えを与えていない新しいオブジェクト

は、ベストプラクティスの両方の観点からこれら大丈夫か?それともポインタを返すべきですか? ベストプラクティスに従うためにどのように変更する必要がありますか?

関数から新しいオブジェクトへの参照を返したいとします。

MyClass& doSomething() { 
    return *(new MyClass()); 
} 

MyClass a = doSomething(); 

MyClassの新しいインスタンスがヒープに新しいもので割り当てられるため、これは問題ありませんか?

これを一定にする必要がありますか(これを行うかどうかはわかりません)。

const MyClass& doSomething() { 
    return *(new MyClass()); 
} 

これらの両方が間違っている場合は、新しいオブジェクトへのポインタを戻すだけでいいですか?

ありがとうございました。

+0

constは必要ありません。最初のオプションは良いです。また、必要に応じてポインタを返すこともできます。あなた次第。 –

+1

しかし、参照は呼び出し元によって割り当てられませんでした。呼び出し中にインスタンス化されました。新しいものを使用しなかった場合、ヒープではなくスタック上にあるため、範囲外になります。 –

+4

@BrianCain彼は絶対に 'new'を必要とします。そうしないと、' doSomething() 'が終了するとすぐにオブジェクトが破壊されるからです。 –

答えて

8

これは間違いではありませんが、それは良い考えではありません。あなたが返された後

MyClass& doSomething() { 
    return *(new MyClass()); 
} 

、誰もが元のポインタを持っていないので、誰もがそれ史上deleteます。*だから、メモリリークです。

対応するdeleteまたはそれ以上のスマートポインタコンストラクタがない限り、newを書くことはほとんどありません。


一方、元のコードでこの行:

MyClass a = doSomething(); 

...とにかく値のコピーを作成しようとしています。それが修正されなければならない別のバグではないと仮定すると、なぜヒープ割り当てをオブジェクトに割り当て、コピーとリークの参照を返しますか?オブジェクトを値で返すだけです。

MyClass doSomething() { 
    return MyClass(); 
} 

ヒープ上に何も作成していないので、何も削除することを心配する必要はありません。


ベストプラクティスは、通常、RAII:Resource Acquisition Is Initializationの4文字で集計できます。 (そしてその結果、その破壊は解放されます。)あなたが値段で回ることは不可能な、あるいは高価な何かを持っているなら、価値によってそれにいくらかのハンドルを渡します。例:

unique_ptr<MyClass> doSomething() { 
    return unique_ptr<MyClass>(new myClass()); 
} 

unique_ptr<MyClass> a = doSomething(); 

これは単なるポインタのコピーです。オブジェクトはdoSomething内に作成され、aがスコープ外になると削除されます(または、別の変数に渡した場合はがスコープ外になるなど)。

一方、MyClassが簡単にコピーできる値のほんの一握り**である場合は、コピーしてください。


*それが今までそれを削除する不可能ではありません。あなたはいつもリファレンスへのポインタをとることができ、それはdeleteです。あなたがそうすることはほとんどありません。それは厄介なように見えます。ポインタを渡す場合は、ポインタを渡します。ポインタを渡す必要がない場合は、クラス内で所有権をラップし、値でクラスを渡します。

**簡単にコピーできるとは、を安全ににコピーして、実際にそうすることを意味します。例えば、生のポインタやファイルハンドルは数バイトで、デフォルトのコピーコンストラクタはあなたを喜んでコピーしますが、同じヒープオブジェクトやファイルへの複数の参照が終わることになります。誰がそれを削除または閉鎖するかを担当しています。

+0

後者はRVOがないと仮定していますか?それとも、私は何かを逃したのですか?(私はしばしばそうします、そうだと思います)。 – WhozCraig

+0

@WhozCraig:RVOの有無にかかわらず、明示的に要求したため、コンパイラは新しく作成されたポインタを最適化できません。参照の代わりに値を返すと、_then_ RVOによってコピーが最適化され、全体が基本的に自由になります。 – abarnert

+0

私は関数の外でクラスを作成して、それを正しい値で渡す必要がありますか?メモリリーク情報をありがとう私は何か変わったと思ったが、私はそれが何だったのか分からなかった。基本的に私が作成しているのは、工場の方法の一種です。だから、ポインタを返すと動作するはずですか? –

関連する問題

 関連する問題