2017-10-06 13 views
2

クラスconstructorは、オブジェクトのアドレスをパラメータとして受け取ります。このクラスのDestructorメモリがヒープ上にあるかどうかを確認しますか?

MyClass(OtherClass * otherClass); 

は私がdeleteOtherClassのインスタンスを試してみてください。

~MyClass() { 
    if(otherClass != nullptr) { 
     delete otherClass; 
    } 
} 

私がいる問題は、私はこのconstructorを呼び出すときに、私は、このように私は以下のようにそれを呼び出す、stackからではなくheapから要素とそれを呼び出すです:

のMyClass MyClassの(& otherObject );

したがって、myClassオブジェクトが範囲外になると例外が発生します。私のOtherObject変数がstackまたはheapに宣言されていればどうすればいいですか?つまり、どうすればオブジェクトをdeleteできますか?

+3

あなたが任意のオブジェクトの所有権のルールを持っていない場合は、コードが混乱になり、あなたはこのような問題を持っているつもりです。通常、ポインタを渡すことは、そのオブジェクトに「所有権を与える」ことです。あなたがそれを望まないなら、それを参照に変更する必要があります。 – tadman

+2

提供された引数の "所有権"を持っているかどうかにかかわらずクラス契約の明確な部分にして、オブジェクトを作成するコードを正しく指定する必要があります。 –

+1

'shared_ptr 'の使用を検討します。あなたは決してそれに与えられた "スタックオブジェクト"を持つことができません。安全面では良いことです –

答えて

5

メモリがヒープかスタックかを区別できるシステム固有のアプローチがありますが、実際には本当に役に立ちません。ヒープ上の別のオブジェクトのメンバへのポインタを持っている可能性があります。メモリはヒープ上にありますが、オブジェクトを削除する責任はありません。別の言い方をしてください:ではありませんあなたがいるパスを下に行く!

問題を処理する適切な方法は、所有権の意味をインターフェイスではっきりと明確にして、それに従うことです。二つの方向は、あなたが取ることができ、基本的にあります。

  1. あなたのクラスは、故意にないは、コンストラクタに渡されたポインタの責任を引き継ぐことができます!代わりに、これらのオブジェクトを処理して、オブジェクトが存在する間にそれらが有効であることを保証するのは、クラスのユーザーの責任です。スタック(またはメンバ)オブジェクトへのポインタを得ることができれば、ユーザはすでにこれらのオブジェクトの有効性を保証する必要があります。ユーザが対処するためには、他の方法std::unique_ptr<OtherClass>
  2. クラスはすべてのオブジェクトを受け取り、それはすべてdeleteになります。 への呼び出し側は、の呼び出し側から、スタックまたはオブジェクトのオブジェクトなど、他の場所で管理されているオブジェクトへのポインタを渡します。

クラスがオブジェクトの責任を何度か持ちますが、必ずしもそうではありません。しかし、このようなアプローチの実装は、実際には上記の2つのアプローチの組み合わせです。適切なスマートポインタをコンストラクタ引数として使用し、スマートポインタがあなたのユーザによって適切に構築されていることを確認するのはユーザの責任ですクラス。たとえば、クラスにはstd::shared_ptr<OtherClass>があり、そのために通常の構成はオブジェクトdeleteになります。ユーザが別の所有オブジェクトへのポインタを渡したい場合、std::shared_ptr<OtherClass>ではないdeleteのポインタを持つディレッタで構築されます。ここでstd::shared_ptrための2つの異なる管理戦略を実証する単純なプログラムです:

#include <iostream> 
#include <memory> 

struct foo { 
    char const* name; 
    foo(char const* name) 
     : name(name) { 
     std::cout << "foo::foo(" << name << "): " << this << "\n"; 
    } 
    ~foo() { 
     std::cout << "foo::~foo(" << name << "): " << this << "\n"; 
    } 
}; 

int main() { 
    std::shared_ptr<foo>(new foo("heap")); 
    foo f("stack"); 
    std::shared_ptr<foo>(&f, [](auto){}); 
} 
+0

システム固有のアプローチでは、おそらく値のスタックポインタ(espまたはrsp)とスタックの底部(esp + offset)。次に、値を比較し、スタックの範囲内にあるかどうかをチェックします。しかし、あなたがそうした場合、あなたのコードは移植可能ではないことを覚えておいてください。 – Asesh

+0

@Asesh:確かに、ほとんどのシステムでは、ポインタがヒープやスタックを参照しているかどうかを知ることができますが、私はこのアプローチを利用することをお勧めしません。 (*)[stackful]コルーチンが利用可能になった場合、コルーチンスタックがヒープからくるので、ポインタがヒープまたはスタックを指しているかどうかを知るのが難しくなります。しかし、これは、オブジェクトの位置を利用しない* [削除するかどうかを決定する]ためのもう一つの理由です。 –

関連する問題