C++类成员布局
在C++中对象的内存布局与类成员声明的顺序一致,静态成员放在数据区(Data Section)而非对象内存中,若多个类静态成员名称相同,C++则按照name mangling技术进行重命名保证名称的唯一性。若类之间发生了继承关系(无虚拟指针无虚继承)时,按照基类、子类成员顺序排列,另在C++对象复制中,有一个规则:基类子对象(base class object)在派生类(derived class member)中成员的原样性。
测试代码如下:
#include <iostream> #include <iomanip> #include <cassert> using namespace std; class Concrete1 { public: void foo(void) { cout << "concrete1:" << bit1 << endl; } Concrete1():val(1),bit1('a') { } public: int val; char bit1; }; class Concrete2:public Concrete1 { public: char bit2; public: void foo(void) { cout << "concreate2" << bit2 << endl; } Concrete2():bit2('b'),Concrete1() { } }; class Concrete3: public Concrete2 { public: void foo(void) { cout << "concrete3:" << bit3 << endl; } Concrete3():bit3('c'),Concrete2() { } public: char bit3; }; template <class data_type1,class data_type2> const char *access_order(data_type1 *mem1,data_type2 *mem2) { unsigned long p1,p2; p1 = (unsigned long)(mem1); p2 = (unsigned long)(mem2); assert(p1 != p2); return p1 < p2 ? "member 1 occurs first" :"member 2 occurs first"; } int main(int argc, char *argv[]) { Concrete2 c2,*pc2; Concrete1 c1,*pc1_1,*pc1_2; Concrete3 c3; pc2 = &c3; pc1_1 = pc2; pc1_2 = &c1; char *b; //access_order(&Concrete1::bit1,&Concrete1::bit); cout << "address val and bit1:" << access_order(&c1.val,&c1.bit1) << endl; cout << "Concrete3:" << sizeof(Concrete3) << endl; //b = *(char *)((char *)(&(pc1_2->bit1)) + 1); b = &(pc1_2->bit1); cout << "Before address:" << hex << static_cast<void *>(b) << ",b:" << *b << endl; b++; cout << "After address:" << hex << static_cast<void *>(b) << endl; cout << "b:" << *b << "b+1:" << *(b+1)<< endl; cout << "Memberwise copy." << endl; *pc1_2 = *pc1_1; //b = *(char *)((char *)(&(pc1_2->bit1)) + 1); b = &(pc1_2->bit1); cout << "Before address:" << hex << static_cast<void *>(b) << ",b:" << *b << endl; b++; cout << "After address:" << hex << static_cast<void *>(b) << endl; cout << "b:" << *b << "b+1:" << *(b+1)<< endl; pc1_2->foo(); return 0; }
g++ 运行情况如下:
f:\code\C++\study>concrete concrete address val and bit1:member 1 occurs first Concrete1:8//三个类大小均为8字节 Concrete2:8 Concrete3:8 Before address:0x22ff34,b:a After address:0x22ff35 b: b+1:" Memberwise copy. //复制前后Concrete1对象填充字节内容未变化 Before address:0x22ff34,b:a After address:0x22ff35 b: b+1:" concrete1:a
vs2010运行如下:
testlayout address val and bit1:member 1 occurs first Concrete1:8//三个类大小均不同,采用了对齐方式处理 Concrete2:12 Concrete3:16 Before address:0012FF40,b:a After address:0012FF41 b:蘠+1: Memberwise copy. //复制前后Concrete1对象填充字节内容未变化 Before address:0012FF40,b:a After address:0012FF41 b:蘠+1: concrete1:a