2017-04-20 8 views
0

メインプログラムで宣言された変数とインスタンス化されたクラスオブジェクト内の変数との間のメモリアドレッシングの違いを理解しようとしています!C++の "インスタンス化されたオブジェクトとオブジェクトの変数の中の変数"のメモリアドレス

私の質問は、メインプログラムの中で "int a、int b"のような2つの変数を宣言するときに、メモリ内の特定の2つのアドレスで4 + 4バイトを取ります。例 "aはメモリ0x248444にあり、bは0x248448にあります" ....この場合は大丈夫です。

2つの変数 "int c、int d"を持つクラスインスタンス化オブジェクトについて言えば、オブジェクトは8バイトの例 "0x248544"のメモリアドレスをとりますが、 "int cとint d"のアドレスはどうですか?

したがって、int cとint dのアドレスは、そのオブジェクトアドレス "0x248544"の内部にありますか? int cとint dには特定のアドレスがありますか?

インスタンス化されたクラスオブジェクトのアドレスとそのオブジェクト内の変数のアドレスの違いは何ですか?

は私の質問が明確であるホープ....

インターネットで検索した後、私は「C++オブジェクト・モデル内」という本を見つけましたが、インスタンス化されたクラスオブジェクトで宣言された変数に関するメモリ差の基本的な理解のためにメインで宣言された変数誰かが私をきれいにする助けてください。

ありがとうございました。

+0

メモリのレイアウトはプラットフォームによって異なります。たとえば、メンバー間のパディングは、特定のプラットフォーム上のメンバータイプのサイズと配置要件によって異なります。最新のスタンダードについてはわかりませんが、しばらくの間、同じアクセス指定子を持つメンバーに対してのみメンバーオーダーが維持されていたことがわかります。 –

+0

related/dupe:http://stackoverflow.com/questions/26939609/how-is-the-memory-layout-of-a-class-vs-a-struct – NathanOliver

+0

クラスオブジェクトは、PODの場合は構造体と同じレイアウトです(パディングを含む)。変数のアドレスは、クラス自体からオフセットされている可能性があります。 'offsetof(cls、some_var) 'を使用できます。 – Brandon

答えて

2

[OK]を、あなたはこのようなクラスCが持っていますしかし、すべてのマシンで)8バイト。

インスタンスがアドレス0x248544にある場合、インスタンスはこのアドレス+次の次のアドレスのバイトを正確に占有します。上記のような単純なクラスでは、さらに条件がなくても、cはこれらの8バイトのうちの最初の4バイトを占有し、次の4バイトはdを占めます。

したがってc.cは、オブジェクトcと全く同じアドレスを持ち、c.dは4バイト後に配置されているため、アドレスは0x248548です。

ただし、最初のメンバーが必ずしもあなたのオブジェクトと同じアドレスを持つとは限りません。私たちのクラスC変更することができます:

class C 
{ 
    virtual ~C() { } // virtual destructor -> C gets virtual! 
    int c; 
    int d; 
}; 

を、はsizeof(C)は16となります(提供ポインタが現代の64ビットハードウェア上として、8バイトのストレージが必要)(!)。どうして?クラスは、通常はクラスCの最初の(しかし見えない)メンバであるvtableへの追加ポインタを取得します。

したがってはまだアドレス0x248544にありますが、vtableへの(目に見えない)ポインタはこのアドレスを共有します。 c.cはその後に来るので、アドレス0x2484cにあり、c.dは0x24850にあります。この点において

、C++は、構造体の最初のメンバーは常に構造体自体のアドレスを共有するC、異なる... CおよびC++で

両方が、しかし、二つの連続メンバーは必ずしもありませんお互いに触れなければならない、いくつかのバイトがパディングされているかもしれない - キーワードのバイトアラインメント。

また、C++クラスのメンバーの順序を変更することを可能にする: Cにおける一方の構造体部材ab前に宣言されている場合、次いでaがメモリ内bの前に配置する必要があり、あまりにも、これは必須C++であります同じアクセシビリティのメンバーのために!あるよう

class C 
{ 
    int a; 
public: 
    int b; 
private: 
    int c; 
}; 

今許可されているコンパイラは順序を残すが、それは他の2のまたは後に前にbを置くことができる - だけac後に配置することが許可されていません。

長い物語、短い結論:このすべてのメモリレイアウトのものは、はるかにあなたは、おそらくそれがあることが予想よりも複雑です...のvtableへ

サイドノート:のvtableポインタが点で(そこにある必要はありませんC++標準へ) - もし、コンパイラベンダーが多態性を実装するためのより良いソリューションを見つけたら、なら、が見つかるでしょう...しかし、vtablesは現在の現状であり、デファクトスタンダードです。

+0

きれいに説明!まさに私が期待していること! ありがとう – Macs

1

クラスインスタンスは、そのメンバ変数のエンベロープと見なすことができます。クラスインスタンスのサイズは、そのメンバ変数のサイズとそれらの間のオプションの埋め込みの合計です。しばしば(継承と多型はこれを混乱させる可能性があります)、最初のメンバ変数のアドレスはclass instanceのアドレスと同じです。メンバのアドレスを取得してデバッガで調査して、その動作を確認することができます。例えば。 cによって占め

class C 
{ 
public: 
    int a = 1; 
    int b = 2; 
}; 

C c; 
int* p_a = &c.a; 
int* p_b = &c.b; 

チェックメモリ、あなたは値12内部を見ることができます。

メンバー変数の順序は保持され、パディングのためにクラスインスタンスのサイズに影響する可能性があります。

空のクラスのインスタンスは、アドレスを持っている必要がありますので、その大きさが0

メンバ関数になることはありません別の話です。それらはメモリのどこかにあるものの、すべてのインスタンスで共有されるため、インスタンスとは別に1か所に格納されます。 - これは必ずしもそうではありません

class C 
{ 
    int c; 
    int d; 
}; 

クラスC(C c)のインスタンスに提供intは4バイトの大きさである(それが必要、いくつかのメモリを占有します:

+0

ご返信ありがとう – Macs

関連する問題