3
 class B
{
   public:
     int a;
     void fn();
}

B のオブジェクトを作成すると、

B* pb = new B;

fn() のメモリはどこにありますか?

オブジェクトに fn() のメモリ位置を指すポインタはありますか?

はいの場合、オブジェクトにポインターがまったくないかのように sizeof(B) が値を返すのはなぜですか?

4

4 に答える 4

15

fn() のメモリはどこにありますか?

これは通常の関数であるため、プログラムのコード セクションのどこかにあります。この場所は、クラスのすべてのインスタンスで同じです。B実際、 viaのインスタンス化とは何の関係もありませんpb

オブジェクトに fn() のメモリ位置を指すポインタはありますか?

いいえ。通常のメンバー関数の場合、アドレスはコンパイル時 (遅くともリンク時) にわかっているため、これは必要ありません。したがって、実行時に個別に保存する必要はありません。

仮想機能の場合、状況は異なります。仮想関数ポインタは配列に格納されます (「仮想関数ポインタ テーブル」または略して「vtable」と呼ばれます)。各クラスにはそのような vtable が 1 つあり、クラスの各インスタンスにはその vtable へのポインターが格納されます。型のポインタ/参照がBaseサブクラスを指しているDerived場合、コンパイラはどの関数を呼び出すかを知る方法がないため、これが必要です。むしろ、関連する vtable で検索することにより、実行時に正しい関数が計算されます。vtable ポインターもsizeofオブジェクトで明らかです。

于 2009-02-18T14:50:41.210 に答える
6

これ:

class B
{
   public:
     int a;
     void fn();
};

すべての実用的な目的で、C コードと同等です。

struct B
{
   int a;
};

void fn(B* bInstance);

C++ バージョンを除いて、bInstance は this ポインターに置き換えられます。両方の関数のメモリがスタックに存在します。では、等価構造体に変換すると、sizeof(B) はどのようになると思いますか?

于 2009-02-18T15:04:38.883 に答える
2

非仮想関数ではなく、仮想関数 (vtable 内) に対して格納されるポインターのみがあります。

于 2009-02-18T14:49:13.520 に答える
1

1) B* pb = new B はヒープにメモリを割り当てます。つまり、特に、delete 演算子を使用して自分でクリーンアップする必要があります。または、ポインターをスマート ポインター (shared_ptr、auto_ptr、scope_ptr) 内に配置して、クリーンアップを実行させることもできます。

2) ポインターは型であるため、オブジェクトまたは null を指し、定義されたサイズ (通常は int に等しい) を持ちます。

3) fn() は仮想関数ではないため、オブジェクト内のメモリは vtable に割り当てられません。

于 2009-02-18T14:53:48.613 に答える