2016-08-24 13 views
4

私は引数としてポインタを必要とする関数をビルドしているので、ポインタの引数を削除することに関するいくつかのスタックオーバーフローの回答を読んでいました。特にこれらのもの(12)です。関数に渡されたポインタを引数として削除する必要がありますか?

機能の簡易版は、以下ではありません:

void draw(Shape * b) 
{ 
    //Draws code.... 
} 

ませ削除何私がここで混乱しています。たとえば、関数が次のように呼び出された場合:

Shape * c; 
draw(&c); 

次に、何も削除する必要はありません。しかし、それはこのような場合:

draw(new Shape{}); 

私はする必要があります。だから基本的には、私の質問は、どのように削除する場合は、newキーワードがパラメータで使用されているかどうかです。関数に投げられる可能性のある例外はないので、RAIIの必要はありません。何か案は?それは私がすでにやっていることなので、スマートポインタを含む何も提案しないでください。この質問は好奇心です。また、関数が新しい演算子または既存のポインタの両方を取ることができるということを知っていれば、基本的に両方を区別する方法が必要です。また、私のリンクの場合:これらの質問のほとんどはスマートなポインタ、または1つのコールまたは他のものに依存しているため、これらの質問には本当に答えません。

+0

誰もが答える:あなたはそのコードが正しい例であることを理解していますか?これは実際のコードではありませんが、同じ答えを生成する(よく考えた)例です。それはコードではなく、実際には削除です。 –

+1

私は答えが例にかかわらず立っていると思います。一般に、生のポインタからオブジェクトの存続期間を伝える方法はありません。 – TartanLlama

答えて

5

は、あなたが使用する可能性があります

void draw(std::observer_ptr<Shape> shape) 

または

void draw(Shape& shape) 

drawが所有権を再利用しないことを明示することが

void draw(Shape * shape) 

オーバー。

スマートポインタを再利用する際に署名に使用します。スマートポインタまたは他のRAIIソリューションの可能性を無視

void Take(std::unique_ptr<Shape> shape); 

または

void Take(std::shared_ptr<Shape> shape); 
+0

すべての回答のうち、これは最も簡単で分かりやすいようです。ありがとうございました! –

2

私は両方を区別するための方法が必要です。

いいえ。この場合、関数はポインタのdeleteをまったく呼び出さないでください。関数の呼び出し側はこの情報を持っており、関数自体ではなく、必要ならポインタ上のdeleteを呼び出す必要があります。

void draw(Shape *&p); 

がからできない場合:

Shape shape; // not pointer 
draw(&shape); 

とから:

+0

あなたはこのコードが正しい例であることを認識していますか?これは実際のコードではありませんが、同じ答えを生成する(よく考えた)例です。それはコードではなく、実際には削除です。 –

+2

私はこれが例であり、答えが同じであることを理解しています - 関数内のポインタを削除しないでください。スマートポインタを使用して所有権を転送するか、呼び出し元がオブジェクトを管理できるようにします。あなたが覚えている醜いハック(メモリがスタックまたはヒープに割り当てられているかどうかを検出しようとする)が大きな問題を生み出します。 – Slava

0

単に機能は、ポインタへの参照を期待するべきである

draw(new Shape()); 
+1

ポインタは動的に割り当てられていないオブジェクトのアドレスを持つ可能性があるため、これは何も変更されません。 – Slava

1

:関数は、与えられたポインタの所有権を取るかどうか、関数の契約の一環として、文書化されなければなりません。

所有権を取得する場合は、その所有者が削除を行います。呼び出し元は後で使用しないでください。

あなたの関数の例はdrawです。その場合、私はそれが所有権を取るべきではないと思います。形を描いてそのまま残しておきます。

4

できないポインターを関数パラメーターとして渡すことはできませんが、通常、作成されたのと同じコンテキストでヒープオブジェクトを削除することをお勧めします。

例えば、私はこれを検討する:

Shape * pShape = new Shape(...); 

draw(pShape); 

delete pShape; 

がこれより優れていることが:

後者の例でも引き分けは()のため deleteを呼び出すことはできませんケースを処理することができなく
draw(new Shape(...)); // Did the shape get deleted? Who knows... 

何らかの理由で、メモリリークが発生する可能性があります。

スマートポインタ(例:​​、shared_ptr<>)を使用してポインタの有効期間を処理することを強くおすすめします。しかし、あなたが絶対にできない場合は、あなたの関数を文書化し、あなたの関数へのポインタの所有権を渡していることと、呼び出し元がdraw()を呼び出した後にpShapeを使うことを期待してはならないと述べていることを確認してください。

5

ここで私が混乱しているのは、削除です。

これは、決して生のポインタを引数として渡さない理由です。、あなたは形状を変更することができる

void draw(const Shape& shape);

    1. あなたは私があなたを渡してい形状を変更しないことがあります。

      はここでは検討する必要があります親指のいくつかのルールです私はそれの所有権を保持しています:

      void draw(Shape& shape);

    2. 私形状のコピーを使用してください:私から離れて、この形状の所有権を取得してください

      void draw(Shape shape);

    3. を:

      void draw(std::unique_ptr<Shape> shape);

    4. のは、この形状を共有しましょう:

      void draw(std::shared_ptr<const Shape> shape);

  • +0

    私はこの回答が非常に良いと思っています。ありがとうございました@RichardHodges、そして+1しました。 –

    関連する問題