2011-07-29 5 views
1

誰も私にここで何が起こっているのか説明できますか?まず、ほとんどのプログラマーは、仮想関数を持つクラスにはvtblがあることを知っているので、その上に余分な4バイトがあります。私が知る限り、それはかなり標準的です。私はこれをテストし、パッチされたvtblsを持つバイナリファイルから適切な場所にロードする前に、この事実を利用しました。過去6ヶ月間、私はXcodeで作業していましたが、ちょうどその場所で何らかの負荷をかける必要が出てきたので、もう一度vtblsにパッチを当てました。私の理解が正しいことを確かめるために、私はサンプルプログラムを書いた。ここにある:仮想関数を持つクラスのサイズGCC/Xcode

class A 
{ 
    public: 
    virtual int getData() 
    { 
     return a; 
    } 

    virtual void print() 
    { 
     printf("hello\n"); 
    } 
    int a; 
}; 

class B : public A 
{ 
public: 
    int getData() 
    { 
     return b; 
    } 
    int b; 
}; 

class C : public B 
{ 
public: 
    int getData() 
    { 
     return c; 
    } 

    void print() 
    { 
     printf("world\n"); 
    } 
    int c; 
}; 

class D 
{ 
public: 
    int a; 
    int b; 
}; 

int main (int argc, const char * argv[]) 
{ 
    A* tA = new A(); 
    tA->a = 1; 

    printf("A: %d\n", sizeof(A)); 
    printf("A data: %d\n", tA->getData()); 

    B* tB = new B(); 
    tB->a = 2; 
    tB->b = 4; 

    printf("B: %d\n", sizeof(B)); 
    printf("B data: %d\n", tB->getData()); 

    C* tC = new C(); 
    tC->c = 8; 

    printf("C: %d\n", sizeof(C)); 
    printf("C data: %d\n", tC->getData()); 

    A* aC = tC; 
    aC->print(); 

    printf("D: %d\n", sizeof(D)); 

    return 0; 
} 

マイ期待出力された:

A:8

データ:1

B:12

Bデータ:4

C:16

Cデータ:8

世界

D:8

しかし、私は取得しています出力は次のようになります。

A:16

データ:1

B:16

Bデータ:4

C:24

Cデータ:8

世界

D:8

誰もがここで何が起こっているか任意のアイデアがありますか?ありがとう!

+3

あなたは64ビットマシンにいますか? – robert

+0

はい、私は - vtblが64ビットを占めるのですか? – alk3ovation

+4

仮想テーブルはポインタです。すべてのポインタは8バイトを占有します。 – robert

答えて

3

クラスA〜Cのインスタンスには、動的タイプの仮想関数テーブルへのポインタvptrが含まれています。このポインターは、64ビットマシンで8バイト(または32ビットマシンで4バイト)を占有します。各intメンバーは4バイトを占有します。

sizeof(Class)の最小値は、すべてのメンバーのsizeof(member)の合計です。それはそのようにした場合は、

sizeof(A) = 8 (vptr) + 4 (int a) = 12 
sizeof(B) = 8 (vptr) + 4 (int a) + 4 (int b) = 16 
sizeof(C) = 8 (vptr) + 4 (int a) + 4 (int b) + 4 (int c) = 20 
sizeof(D) = 4 (int a) + 4 (int b) = 8 

しかし、これが唯一の最小サイズです。コンパイラは通常このサイズをsizeof(void *)の倍数にします。これは8バイトです。このプロセスはと一致し、となります。このようにメモリが浪費されるように見えるかもしれませんが、これはパフォーマンスの向上よりも優れています。CPUは、アライメントされていないデータよりもはるかに高速にアライメントされたデータを読み取ることができます。

ちなみに、32ビットマシンを使用していた場合、期待した結果が得られているはずです。ポインタ(特にvptr)は4バイト幅であり、アライメントは4バイトの倍数にもなります。問題のクラスのすべてのデータメンバーが4バイト大きいので、整列はそこで何もしません。

関連する問題