• ベストアンサー

基本クラスポインタ = new 派生クラス[i];

基本クラスのポインタ変数pbaseを宣言し、new演算子にて派生クラスの配列を動的に確保して、pbaseに代入した場合、delete[] pbaseは上手く動作するのでしょうか。 (Aのデストラクタは仮想関数にしてあるとしておきます) ------ex-start------ class A {}; class b:public A{}; main() {   A * pbase   pbase = new B[5];   delete[] pbase } ------ex-end------ 例えば、 class Aは12バイト class Bは20バイト である場合、配列のサイズが違うのに、delete[]でちゃんと開放されるのでしょうか。 それともnew/deleteは確保したサイズをシンボル毎に記憶しているのでしょうか。 どうもこの辺が曖昧で実装する時にあやふやになってしまいます。どなたかお知恵をお貸しくださいませ。

質問者が選んだベストアンサー

  • ベストアンサー
  • jmh
  • ベストアンサー率23% (71/304)
回答No.3

struct A { int x; virtual ~A() { cout << "~A: " << this << endl; } }; struct B: A { int y; ~B() { cout << "~B: " << this << endl; } }; B *b = new B[5]; A *a = b; A *a2= a + 2; a2->x = 1; delete[] a; これを素朴に考えると a2 は単純に a に 2 * sizeof(A) バイト足した場所(b[1] と b[2] の中間ぐらい?)を指すかもしれないです。a2->x = 1 は危険な感じがします。 delete [] が、配列の各要素のデストラクタに渡す this を求めるときに同様の失敗をするかもしれないです。 …と今日まで思っていましたが、実際やってみると delete[] で new B[5] が削除できてしまいました(VC++6.0)。不思議です。

tamanegi_majin
質問者

お礼

http://lagendra.s.kanazawa-u.ac.jp/ogurisu/manuals/c/C-faq/C-faq-07.html 7.26に有りました。 メモリが動的に確保された時はそのブロックサイズが記憶されていると予測できます。 と言う事は、ポインタの値が同じならば開放されると言う事っぽいです。その辺は保証されているか不明ですが。 ともかく疑問が消えましたありがとうございます。

tamanegi_majin
質問者

補足

私も、同じような事が出来る事を確認しました。 派生クラスに別のクラスのオブジェクトをメンバとして持たせて、そのデストラクタが呼ばれるかどうかと言うやり方でしたが。 結果は、開放されますね。 初歩的な質問になるのでしょうけれども、free()/deleteで「ポインタ」しか渡しませんよね。 確保されているサイズは渡していないのですが、これってmalloc()/newの時にどこかに記録されてるって事なんですかね。

その他の回答 (2)

回答No.2

シンボル毎というか、オブジェクトごとに大きさを管理していますので、問題なく開放されます。デフォルトのnew/delete演算子は以下の定義です。クラスの区別はなく、大きさのみが渡されます。また、delete演算子はメモリポインタのみです。通常、malloc関数とfree関数で実装されています。 void* operator new [] (size_t sz) { return (void*)malloc(sz); } void operator delete [] (void* pAlloc) { free (pAlloc); }

tamanegi_majin
質問者

補足

ありがとうございます。助かります。 ということは以下の場合も大丈夫なのでしょうか。 ------ex-start------ class A {}; class B:public A{}; main() {   A * pbase;   B * pdri;   pdri = new B[5];   pbase = pdri;   delete[] pbase; } ------ex-end------ 以上の場合と、質問の場合の区別がいまいちつきません。 実行動作はなんとなくわかるのですが。

回答No.1

デストラクターを仮想にしているので問題ないと思います。これはアップキャストの話ですよね。 検索するといろいろ出てきますが適当な一つを紹介しておきます。

参考URL:
http://www1.kcn.ne.jp/~robe/cpphtml/html02/cpp02015.html
tamanegi_majin
質問者

補足

ありがとうございます。助かります。 アップキャストで気になっているのですが、 基底クラスのポインタに、派生クラスのオブジェクトの配列を渡した場合、派生クラスのメンバ変数にアクセスすることは出来ないのでしょうか。 A pbase; pbase = new B[4]; とした場合、Bのメンバ変数にアクセスする場合、もう一度キャストしなおしてやらなくてはいけないのでしょうか。 大本として、これが気になっているのですが。

関連するQ&A

専門家に質問してみよう