「これはヤバかったな」という遅刻エピソード

基本クラスのポインタ変数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は確保したサイズをシンボル毎に記憶しているのでしょうか。
どうもこの辺が曖昧で実装する時にあやふやになってしまいます。どなたかお知恵をお貸しくださいませ。

A 回答 (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)。不思議です。

この回答への補足

私も、同じような事が出来る事を確認しました。
派生クラスに別のクラスのオブジェクトをメンバとして持たせて、そのデストラクタが呼ばれるかどうかと言うやり方でしたが。
結果は、開放されますね。


初歩的な質問になるのでしょうけれども、free()/deleteで「ポインタ」しか渡しませんよね。
確保されているサイズは渡していないのですが、これってmalloc()/newの時にどこかに記録されてるって事なんですかね。

補足日時:2003/06/24 12:15
    • good
    • 0
この回答へのお礼

http://lagendra.s.kanazawa-u.ac.jp/ogurisu/manua …

7.26に有りました。
メモリが動的に確保された時はそのブロックサイズが記憶されていると予測できます。
と言う事は、ポインタの値が同じならば開放されると言う事っぽいです。その辺は保証されているか不明ですが。

ともかく疑問が消えましたありがとうございます。

お礼日時:2003/06/24 12:23

シンボル毎というか、オブジェクトごとに大きさを管理していますので、問題なく開放されます。

デフォルトのnew/delete演算子は以下の定義です。クラスの区別はなく、大きさのみが渡されます。また、delete演算子はメモリポインタのみです。通常、malloc関数とfree関数で実装されています。

void* operator new [] (size_t sz)
{
return (void*)malloc(sz);
}
void operator delete [] (void* pAlloc)
{
free (pAlloc);
}

この回答への補足

ありがとうございます。助かります。
ということは以下の場合も大丈夫なのでしょうか。

------ex-start------
class A {};
class B:public A{};

main()
{
  A * pbase;
  B * pdri;

  pdri = new B[5];
  pbase = pdri;

  delete[] pbase;
}
------ex-end------

以上の場合と、質問の場合の区別がいまいちつきません。
実行動作はなんとなくわかるのですが。

補足日時:2003/06/23 22:54
    • good
    • 0

デストラクターを仮想にしているので問題ないと思います。

これはアップキャストの話ですよね。
検索するといろいろ出てきますが適当な一つを紹介しておきます。

参考URL:http://www1.kcn.ne.jp/~robe/cpphtml/html02/cpp02 …

この回答への補足

ありがとうございます。助かります。
アップキャストで気になっているのですが、
基底クラスのポインタに、派生クラスのオブジェクトの配列を渡した場合、派生クラスのメンバ変数にアクセスすることは出来ないのでしょうか。

A pbase;
pbase = new B[4];

とした場合、Bのメンバ変数にアクセスする場合、もう一度キャストしなおしてやらなくてはいけないのでしょうか。

大本として、これが気になっているのですが。

補足日時:2003/06/23 22:57
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!