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
C++类成员布局的更多相关文章
- C++类内存布局图(成员函数和成员变量分开讨论)
一.成员函数 成员函数可以被看作是类作用域的全局函数,不在对象分配的空间里,只有虚函数才会在类对象里有一个指针,存放虚函数的地址等相关信息. 成员函数的地址,编译期就已确定,并静态绑定或动态的绑定在对 ...
- Objective-C类成员变量深度剖析
目录 Non Fragile ivars 为什么Non Fragile ivars很关键 如何寻址类成员变量 真正的“如何寻址类成员变量” Non Fragile ivars布局调整 为什么Objec ...
- C#定义类成员
1.成员定义 public--成员可以由任何代码访问. private--成员只能由类中的代码访问(如果没有使用任何关键字,就默认使用这个关键字). internal--成员只能由定义它的程序集(项目 ...
- 理解ATL中的一些汇编代码(通过Thunk技术来调用类成员函数)
我们知道ATL(活动模板库)是一套很小巧高效的COM开发库,它本身的核心文件其实没几个,COM相关的(主要是atlbase.h, atlcom.h),另外还有一个窗口相关的(atlwin.h), 所以 ...
- c++空指针调用类成员函数
最近在看C++动态绑定问题时(理解静态绑定时)发现的问题:能用空指针调用类的成员函数(gcc,vs2013下都可以). 例子: class animal { public: void sleep(){ ...
- 深入理解类成员函数的调用规则(理解成员函数的内存为什么不会反映在sizeof运算符上、类的静态绑定与动态绑定、虚函数表)
本文转载自:http://blog.51cto.com/9291927/2148695 总结: 一.成员函数的内存为什么不会反映在sizeof运算符上? 成员函数可以被看作是类 ...
- Objective-C类成员变量深度剖析--oc对象内存模型
目录 Non Fragile ivars 为什么Non Fragile ivars很关键 如何寻址类成员变量 真正的“如何寻址类成员变量” Non Fragile ivars布局调整 为什么Objec ...
- OC基础--结构体 枚举做类成员属性
结构体 枚举作类的成员属性: 定义一个学生类 性别 -- 枚举 生日 入学日期 毕业日期 -- 结构体 代码示例: 声明文件 Student.h: #import <Foundation ...
- 重载运算符:类成员函数or友元函数
类成员函数: bool operator ==(const point &a)const { return x==a.x; } 友元函数: friend bool operator ==(co ...
随机推荐
- AutoCAD学习笔记
学习笔记: **有些命令,有两到三种执行方式:菜单.命令行.对话框.如layer命令,如果在命令行打入layer命令,就会弹出对话框主y式,如果要命令行方式执行,就需要在前面加一个-号,即-layer ...
- GDAL C# 开发出现的异常
在使用开发C#下的GDAL时,编译时正确. 在执行 Gdal.AllRegister(); 出现异常:OSGeo.GDAL.GdalPINVOKE”的类型初始值设定项引发异常. 解决方案: 编译正常, ...
- -canOpenURL: failed for URL: "" - error: "(null)" , iOS9 App传输安全 支持http 解决方案
-canOpenURL: failed for URL: "CamCardHDOpenAPI:*" - error: "(null)" This app is ...
- curl post
//Post方式实现 $url = "http://localhost/web_services.php"; $post_data = array ("username& ...
- AVLTree 平衡树
//测试数据//第一组:7个输入,测试LL型,40,36,44,32,38,28,24://第二组:7个输入,测试RR型,40,36,44,43,48,52,56://第三组:7个输入,测试LR型,4 ...
- JAVA中SERIALVERSIONUID的解释
serialVersionUID作用: 序列化时为了保持版本的兼容性,即在版本升级时反序列化仍保持对象的唯一性.有两种生成方式: 一个是默认的1L,比如:private st ...
- 【转】关于Oracle将小于1的数字to_char后丢掉0的解决办法
SQL代码如下: select rtrim(to_char(0.11, 'fm9990.99'), '.') from dual; 其中0.11为需要to_char的数字fm去掉字符串前面的空格999 ...
- 一个比较综合的项目--》>图片缓存,下拉刷新等
在办公室电脑(E:\workspace\23\Collections)
- Python的平凡之路(14)
一.什么是HTML HTML(Hyper Text Mark-up Language ) 即超文本标记语言,是 WWW 的描述语言,由 Tim Berners-lee提出.设计 HTML 语言的目的是 ...
- js回车动态添加表格,右键动态删除表格行
<script type="text/javascript" language="javascript">//屏蔽浏览器右键function sto ...