![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?e8efa67)
基本クラスのポインタ変数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は確保したサイズをシンボル毎に記憶しているのでしょうか。
どうもこの辺が曖昧で実装する時にあやふやになってしまいます。どなたかお知恵をお貸しくださいませ。
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)。不思議です。
この回答への補足
私も、同じような事が出来る事を確認しました。
派生クラスに別のクラスのオブジェクトをメンバとして持たせて、そのデストラクタが呼ばれるかどうかと言うやり方でしたが。
結果は、開放されますね。
初歩的な質問になるのでしょうけれども、free()/deleteで「ポインタ」しか渡しませんよね。
確保されているサイズは渡していないのですが、これってmalloc()/newの時にどこかに記録されてるって事なんですかね。
http://lagendra.s.kanazawa-u.ac.jp/ogurisu/manua …
7.26に有りました。
メモリが動的に確保された時はそのブロックサイズが記憶されていると予測できます。
と言う事は、ポインタの値が同じならば開放されると言う事っぽいです。その辺は保証されているか不明ですが。
ともかく疑問が消えましたありがとうございます。
No.2
- 回答日時:
シンボル毎というか、オブジェクトごとに大きさを管理していますので、問題なく開放されます。
デフォルトの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------
以上の場合と、質問の場合の区別がいまいちつきません。
実行動作はなんとなくわかるのですが。
No.1
- 回答日時:
デストラクターを仮想にしているので問題ないと思います。
これはアップキャストの話ですよね。検索するといろいろ出てきますが適当な一つを紹介しておきます。
参考URL:http://www1.kcn.ne.jp/~robe/cpphtml/html02/cpp02 …
この回答への補足
ありがとうございます。助かります。
アップキャストで気になっているのですが、
基底クラスのポインタに、派生クラスのオブジェクトの配列を渡した場合、派生クラスのメンバ変数にアクセスすることは出来ないのでしょうか。
A pbase;
pbase = new B[4];
とした場合、Bのメンバ変数にアクセスする場合、もう一度キャストしなおしてやらなくてはいけないのでしょうか。
大本として、これが気になっているのですが。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
関数から配列を返すには?
-
c言語
-
配列の要素数に変数を入れたい...
-
define で 配列
-
MFC - ダイアログボックスのPic...
-
基本クラスポインタ = new 派生...
-
IPアドレスを配列に代入する方法。
-
C#で配列が空かを判定するには?
-
fclose()でセグメンテーション違反
-
コンボボックスでデフォルト値...
-
C#で構造体の配列を持った構造...
-
三次元配列の動的メモリの確保?
-
万年カレンダーについて。
-
シマウマの模様を変えるプログラム
-
VBAのプログラムで、DIAG = 1# ...
-
C言語 配列の長さの上限
-
fopne で失敗する原因
-
WSH(VBS)でJSONの文字列を読み...
-
セグメントエラー
-
C# Listを使わずに2次元配列の...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
関数から配列を返すには?
-
構造体のextern方法
-
配列の要素数に変数を入れたい...
-
C言語において、 配列要素をひ...
-
define で 配列
-
c言語
-
C#で構造体の配列を持った構造...
-
C言語 ファイルの指定された行...
-
c言語 構造体
-
コンボボックスでデフォルト値...
-
配列のアドレス部
-
MFCのCArrayを使った二次元配列
-
MFC - ダイアログボックスのPic...
-
C言語についてです 5人のテスト...
-
C言語から質問です。
-
AfxBeginThread の引数について
-
C言語の課題が出たのですが自力...
-
Cのエラー
-
int i, int i[1];
-
C#で配列が空かを判定するには?
おすすめ情報