在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. 前端面试题之Html和CSS

    又到了毕业季,很多小伙伴们都到了找工作的时候了,好多小伙伴问我有前端的面试题么?答:没有. 呃呃… … 小伙伴本宝宝真的没有骗你们,我从毕业到现在一直在一家公司没有换过,所以手里压根没有面试题.我们公 ...

  2. 更改星级评分条 RatingBar 的样式

    1.首先在布局中引用星级评分条: <RatingBar            android:id="@+id/room_ratingbar"            styl ...

  3. .NET截取指定长度汉字超出部分以"..."代替

    /// <summary> /// 将指定字符串按指定长度进行剪切, /// </summary> /// <param name= "oldStr " ...

  4. 【转】Swift之 ? 和 !

    原文地址:http://joeyio.com/ios/2014/06/04/swift---/ Swift语言使用var定义变量,但和别的语言不同,Swift里不会自动给变量赋初始值,也就是说变量不会 ...

  5. (DFS、全排列)POJ-2718 Smallest Difference

    题目地址 简要题意: 给若干组数字,每组数据是递增的在0--9之间的数,且每组数的个数不确定.对于每组数,输出由这些数组成的两个数的差的绝对值最小是多少(每个数出现且只出现一次). 思路分析: 对于n ...

  6. SpringMVC 视图和视图解析器&表单标签

    视图和视图解析器 请求处理方法执行完成后,最终返回一个 ModelAndView 对象.对于那些返回 String,View 或 ModeMap 等类型的处理方法,Spring MVC 也会在内部将它 ...

  7. 用powershell+excel行列转置三步走

    本文重点讲解第一步,手动在excel表中输入公式,或者用powershell自动输入公式. 第二步,用powershell向excel中写入数据,略. 第三步,用powershell从excel中读取 ...

  8. 当在浏览器输入一个url访问后发生了什么

    首先根据DNS获取该url的ip地址,ip地址的获取可能通过本地缓存,路由缓存等得到. 然后在网络层通过路由选择查找一条可达路径,最后利用tcp/ip协议来进行数据的传输. 其中在传输层将信息添加源端 ...

  9. 在一台机器上模拟mongodb分片

    首先选择一个目录在其中建立以下2个文件夹:data和log 在data下建立9个文件夹: 其中前3个为配置服务器所在文件夹,按照官网要求,一个集群需要3个config server rs-a-n和rs ...

  10. python中if __name__ == '__main__': 的解析

    当你打开一个.py文件时,经常会在代码的最下面看到if __name__ ==  '__main__':,现在就来介 绍一下它的作用. 模块是对象,并且所有的模块都有一个内置属性 __name__.一 ...