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 ...
随机推荐
- JQUERY MOBILE 中文API站 和 官方论坛
中文API站:http://www.jqmapi.com/api1.2/preview/quickstartquide.html 官方论坛:http://bbs.phonegapcn.com/foru ...
- SQL指定字段指定顺序排序
SELECT * FROM [ProjectInfo]ORDER BY (CASE DepartmentName WHEN 'AAA' THEN 1 WHEN 'BBB' THEN 2 WHEN 'C ...
- mysql-5.6.17-win32的安装?
官方mysql最新版本:http://cdn.mysql.com/Downloads/MySQL-5.6/mysql-5.6.17.tar.gz 解压后,以管理员的身份打开cmd.exe,切入安装目录 ...
- Cookie与Session用法
以下是Cookie的完整实例 MyEclipse新建web Project工程,建两个jsp文件,如下 1.login.jsp <%@ page language="java" ...
- isMobile
var isMobile = { Android: function() { return navigator.userAgent.match(/Android/i); }, BlackBerry: ...
- 完全卸载oracle11g步骤【转】
重装oralce,每次都很蛋疼.找了个比较全的步骤.留作备份. 完全卸载oracle11g步骤:1. 开始->设置->控制面板->管理工具->服务 停止所有Oracle服务.2 ...
- 关于WebView的复习
最近不知为啥,公司提出要用webView,偷笑不止.在青软上课的时候学过这东西,是说条件比较紧张的时候可以拿来充数的,现在公司里手机端开发人员很多,做的好好的,放着原生ui不用,非要赶时髦搞什么Web ...
- 对客户推荐产品模型+python代码
首先观看数据: l 数据的基本特征用 describe 描述每个基本特征 l 画图画出每个特征的基本统计图 应用import matplotlib.pylab as pl 画图显示 l 关 ...
- 浅谈大数据神器Spark中的RDD
1.究竟什么是RDD呢? 有人可能会回答是:Resilient Distributed Dataset.没错,的确是如此.但是我们问这个实际上是想知道RDD到底是个什么东西?以及它到底能干嘛?好的,有 ...
- mysql关于timestamp类型
数据库设置时间字段为timestamp类型,DTO设置为java.util.Date类型.DTO设值sessionLogDTO.setLoginOutTime(new Date());用new Dat ...