在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++类成员布局的更多相关文章

  1. C++类内存布局图(成员函数和成员变量分开讨论)

    一.成员函数 成员函数可以被看作是类作用域的全局函数,不在对象分配的空间里,只有虚函数才会在类对象里有一个指针,存放虚函数的地址等相关信息. 成员函数的地址,编译期就已确定,并静态绑定或动态的绑定在对 ...

  2. Objective-C类成员变量深度剖析

    目录 Non Fragile ivars 为什么Non Fragile ivars很关键 如何寻址类成员变量 真正的“如何寻址类成员变量” Non Fragile ivars布局调整 为什么Objec ...

  3. C#定义类成员

    1.成员定义 public--成员可以由任何代码访问. private--成员只能由类中的代码访问(如果没有使用任何关键字,就默认使用这个关键字). internal--成员只能由定义它的程序集(项目 ...

  4. 理解ATL中的一些汇编代码(通过Thunk技术来调用类成员函数)

    我们知道ATL(活动模板库)是一套很小巧高效的COM开发库,它本身的核心文件其实没几个,COM相关的(主要是atlbase.h, atlcom.h),另外还有一个窗口相关的(atlwin.h), 所以 ...

  5. c++空指针调用类成员函数

    最近在看C++动态绑定问题时(理解静态绑定时)发现的问题:能用空指针调用类的成员函数(gcc,vs2013下都可以). 例子: class animal { public: void sleep(){ ...

  6. 深入理解类成员函数的调用规则(理解成员函数的内存为什么不会反映在sizeof运算符上、类的静态绑定与动态绑定、虚函数表)

    本文转载自:http://blog.51cto.com/9291927/2148695 总结: 一.成员函数的内存为什么不会反映在sizeof运算符上?             成员函数可以被看作是类 ...

  7. Objective-C类成员变量深度剖析--oc对象内存模型

    目录 Non Fragile ivars 为什么Non Fragile ivars很关键 如何寻址类成员变量 真正的“如何寻址类成员变量” Non Fragile ivars布局调整 为什么Objec ...

  8. OC基础--结构体 枚举做类成员属性

    结构体  枚举作类的成员属性: 定义一个学生类 性别 -- 枚举 生日 入学日期  毕业日期  --  结构体 代码示例: 声明文件 Student.h: #import <Foundation ...

  9. 重载运算符:类成员函数or友元函数

    类成员函数: bool operator ==(const point &a)const { return x==a.x; } 友元函数: friend bool operator ==(co ...

随机推荐

  1. JQUERY MOBILE 中文API站 和 官方论坛

    中文API站:http://www.jqmapi.com/api1.2/preview/quickstartquide.html 官方论坛:http://bbs.phonegapcn.com/foru ...

  2. SQL指定字段指定顺序排序

    SELECT * FROM [ProjectInfo]ORDER BY (CASE DepartmentName WHEN 'AAA' THEN 1 WHEN 'BBB' THEN 2 WHEN 'C ...

  3. mysql-5.6.17-win32的安装?

    官方mysql最新版本:http://cdn.mysql.com/Downloads/MySQL-5.6/mysql-5.6.17.tar.gz 解压后,以管理员的身份打开cmd.exe,切入安装目录 ...

  4. Cookie与Session用法

    以下是Cookie的完整实例 MyEclipse新建web Project工程,建两个jsp文件,如下 1.login.jsp <%@ page language="java" ...

  5. isMobile

    var isMobile = { Android: function() { return navigator.userAgent.match(/Android/i); }, BlackBerry: ...

  6. 完全卸载oracle11g步骤【转】

    重装oralce,每次都很蛋疼.找了个比较全的步骤.留作备份. 完全卸载oracle11g步骤:1. 开始->设置->控制面板->管理工具->服务 停止所有Oracle服务.2 ...

  7. 关于WebView的复习

    最近不知为啥,公司提出要用webView,偷笑不止.在青软上课的时候学过这东西,是说条件比较紧张的时候可以拿来充数的,现在公司里手机端开发人员很多,做的好好的,放着原生ui不用,非要赶时髦搞什么Web ...

  8. 对客户推荐产品模型+python代码

    首先观看数据: l  数据的基本特征用  describe  描述每个基本特征 l  画图画出每个特征的基本统计图 应用import matplotlib.pylab as pl  画图显示 l  关 ...

  9. 浅谈大数据神器Spark中的RDD

    1.究竟什么是RDD呢? 有人可能会回答是:Resilient Distributed Dataset.没错,的确是如此.但是我们问这个实际上是想知道RDD到底是个什么东西?以及它到底能干嘛?好的,有 ...

  10. mysql关于timestamp类型

    数据库设置时间字段为timestamp类型,DTO设置为java.util.Date类型.DTO设值sessionLogDTO.setLoginOutTime(new Date());用new Dat ...