有了前面几节的铺垫,本节开始摸索C++的对象的内存布局,平台为windows32位+VS2008。

一 内置类型的size

内置类型,直接上代码,帮助大家加深记忆:

Code
void TestBasicSizeOf()
{
    cout << __FUNCTION__ << endl;

cout << "  sizeof(char)= " << sizeof ( char ) << endl;
    cout << "  sizeof(int)= " << sizeof ( int ) << endl;
    cout << "  sizeof(float)= " << sizeof ( float ) << endl;
    cout << "  sizeof(double)= " << sizeof ( double ) << endl;

cout << "  sizeof('$')=" << sizeof ( '$' ) << endl;
    cout << "  sizeof(1)= " << sizeof ( 1 ) << endl;
    cout << "  sizeof(1.5f)= " << sizeof ( 1.5f ) << endl;
    cout << "  sizeof(1.5)= " << sizeof ( 1.5 ) << endl;

cout << "  sizeof(Good!)= " << sizeof ( "Good!" ) << endl ;

char  str[] = "CharArray!";
    int  a[10]; 
    double  xy[10];
    cout << "  char str[] = \"CharArray!\"," << " sizeof(str)= " << sizeof (str) << endl;
    cout << "  int a[10]," << " sizeof(a)= " << sizeof (a) << endl;
    cout << "  double xy[10]," << " sizeof(xy)= " <<   sizeof (xy) << endl;

cout << "  sizeof(void*)= " << sizeof(void*) << endl;
}

运行结果如下:

二 struct/class的大小

在C++中我们知道struct和class的唯一区别就是默认的访问级别不同,struct默认为public,而class的默认为private。所以考虑对象的大小,我们均以struct为例。对于struct的大小对于初学者来说还确实是个难回答的问题,我们就通过下面的一个struct定义加逐步的变化来引出相关的知识。

代码如下:

Code
struct st1
{
    short number;
    float math_grade;
    float Chinese_grade;
    float sum_grade;
    char  level;
}; //20

struct st2
{
    char  level;
    short number;
    float math_grade;
    float Chinese_grade;
    float sum_grade;
};//16

#pragma pack(1)
struct st3
{
    char  level;
    short number;
    float math_grade;
    float Chinese_grade;
    float sum_grade;
}; //15
#pragma pack()

void TestStructSizeOf()
{
    cout << __FUNCTION__ << endl;

cout << "  sizeof(st1)= " << sizeof (st1) << endl;
    cout << "  offsetof(st1,number) " << offsetof(st1,number) << endl;
    cout << "  offsetof(st1,math_grade) " << offsetof(st1,math_grade) << endl;
    cout << "  offsetof(st1,Chinese_grade) " << offsetof(st1,Chinese_grade) << endl;
    cout << "  offsetof(st1,sum_grade) " << offsetof(st1,sum_grade) << endl;
    cout << "  offsetof(st1,level) " << offsetof(st1,level) << endl;

cout << "  sizeof(st2)= " << sizeof (st2) << endl;
    cout << "  offsetof(st2,level) " << offsetof(st2,level) << endl;
    cout << "  offsetof(st2,number) " << offsetof(st2,number) << endl;
    cout << "  offsetof(st2,math_grade) " << offsetof(st2,math_grade) << endl;
    cout << "  offsetof(st2,Chinese_grade) " << offsetof(st2,Chinese_grade) << endl;
    cout << "  offsetof(st2,sum_grade) " << offsetof(st2,sum_grade) << endl;

cout << "  sizeof(st3)= " << sizeof (st3) << endl;
    cout << "  offsetof(st3,level) " << offsetof(st3,level) << endl;
    cout << "  offsetof(st3,number) " << offsetof(st3,number) << endl;
    cout << "  offsetof(st3,math_grade) " << offsetof(st3,math_grade) << endl;
    cout << "  offsetof(st3,Chinese_grade) " << offsetof(st3,Chinese_grade) << endl;
    cout << "  offsetof(st3,sum_grade) " << offsetof(st3,sum_grade) << endl;
}

运行结果如下;

基于上面的对struct的测试,我们是不是有些惊呆哦,对于C++的初学者更是情不自禁的说:“我靠!原来顺序不同所占空间都不同啊,还有那个pack是啥东东啊?”,其实这里蕴含了一个内存对齐的问题,在计算机的底层进行内存的读写的时候,如果内存对齐的话可以提高读写效率,下面是VC的默认规则:

1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
2) 结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍, 如有需要编译器会在成员之间加上填充字节(internal adding);
3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节(trailing padding)。

当然VC提供了工程选项/Zp[1|2|4|8|16]可以修改对齐方式,当然我们也可以在代码中对部分类型实行特殊的内存对齐方式,修改方式为#pragma pack( n ),n为字节对齐
数,其取值为1、2、4、8、16,默认是8,取消修改用#pragma pack(),如果结构体某成员的sizeof大于你设置的,则按你的设置来对齐。

三 struct的嵌套

1)实例:

Code
struct A
{
    int i;
    char c;
    double d;
    short s;
}; // 24

struct B
{
    char cc;
    A a;
    int ii;
}; // 40

布局:(使用VS的未发布的编译选项/d1 reportAllClassLayout 或 /d1 reportSingleClassLayout)

2)实例:

Code
#pragma pack(4)
struct A2
{
    int i;
    char c;
    double d;
    short s;
}; // 20
#pragma pack()

struct B2
{
    char cc;
    A2 a;
    int ii;
}; // 28

布局:(使用VS的未发布的编译选项/d1 reportAllClassLayout 或 /d1 reportSingleClassLayout)

总结:

  由于结构体的成员可以是复合类型,比如另外一个结构体,所以在寻找最宽基本类型成员时,应当包括复合类型成员的子成员,而不是把复合成员看成是一个整体。但在确定复合类型成员的偏移位置时则是将复合类型作为整体看待。

四 空struct/class和const,static成员

实例:

Code
struct empty{}; // 1
struct constAndStatic
{
    const int i;
    static char c;
    const double d;
    static void TestStatic(){}
    void TestNoStatic(){}
}; // 16

布局:(使用VS的未发布的编译选项/d1 reportAllClassLayout 或 /d1 reportSingleClassLayout)

上面的实例中empty的大小为1,而constAndStatic的大小为16。

总结:

因为static成员和函数其实是类层次的,不在对象中分配空间,而成员函数其实是被编译为全局函数了,所以也不在对象中。

五 本节完,下次探讨虚函数对内存布局的影响!

转载于:https://www.cnblogs.com/itech/archive/2009/02/25/1396740.html

[C++对象模型][6]sizeof与对象内存布局相关推荐

  1. 【C++】C++对象模型:对象内存布局详解(C#实例)

    C++对象模型:对象内存布局详解 0.前言 C++对象的内存布局.虚表指针.虚基类指针解的探讨,参考. 1.何为C++对象模型? 引用<深度探索C++对象模型>这本书中的话: 有两个概念可 ...

  2. 图说C++对象模型:对象内存布局详解

    目录 1.何为C++对象模型? 2.文章内容简介 3.理解虚函数表 3.1.多态与虚表 3.2.使用指针访问虚表 4.对象模型概述 4.1.简单对象模型 4.2.表格驱动模型 4.3.非继承下的C++ ...

  3. C++对象内存布局--①测试虚函数表属于类

    C++对象内存布局--①测试虚函数表属于类 测试1:同一个类的多个对象共享同一张虚函数表.   //虚函数表.cpp //2010年8月18日 //测试虚函数表,说明虚函数表属于类所有.同一个类的多个 ...

  4. C++对象内存布局--⑤GCC编译器--单个虚拟继承

    C++对象内存布局--⑤GCC编译器--单个虚拟继承 测试GNU的GCC编译器在处理虚拟继承上跟VS不同的地方.派生类的虚函数表跟虚基类表合并. //GCC编译器--单个虚拟继承.cpp //2010 ...

  5. C++对象内存布局--③测试多继承中派生类的虚函数在哪一张虚函数表中

    C++对象内存布局--③测试多继承中派生类的虚函数在哪一张虚函数表中 测试2:证明派生类的虚函数的地址跟第一基类的虚函数地址保存在同一张虚函数表中. 派生类有多少个拥有虚函数的基类,派生类对象就有多少 ...

  6. C++对象内存布局--④VS编译器--单个虚拟继承

    C++对象内存布局--④VS编译器--单个虚拟继承 在VS2005编译器下,证明单个虚拟继承的内存布局:无论有无虚函数,必然含有虚基类表指针.虚基类表中的内容为本类实例的偏移和基类实例的相对偏移值. ...

  7. C字节对齐与C++类对象内存布局

    一.什么是对齐,以及为什么要对齐: 1. 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定变量的时候经常在特定的内存地址访问, ...

  8. C++对象内存布局测试总结

    C++对象内存布局测试总结 http://hi.baidu.com/����/blog/item/826d38ff13c32e3a5d6008e8.html 上文是半年前对虚函数.虚拟继承的理解.可能 ...

  9. java char占用多少字节_Java虚拟机:Java对象大小、对象内存布局及锁状态变化

    一个对象占多少字节? 关于对象的大小,对于C/C++来说,都是有sizeof函数可以直接获取的,但是Java似乎没有这样的方法.不过还好,在JDK1.5之后引入了Instrumentation类,这个 ...

最新文章

  1. 1998-1999图灵奖
  2. 数据挖掘SPSS Clementine 12.0.3 多国语言(含中文)破解版
  3. zoj 3696 Alien's Organ(泊松分布)
  4. 北京卫生中级英语计算机考试成绩查询,2019年北京卫生专业技术资格成绩查询时间及入口...
  5. WinPcap 获取本地适配器信息
  6. Java IO流及应用(一)
  7. java 数据截断_java – 数据截断:第1行的列’标志’的数据太长
  8. .NET Core 下使用 Exceptionless 记录日志
  9. STN可以增强CNN网络
  10. 21天学通python-21天学通python
  11. Cisco-NetDevOps-CI/CD-Experiment Workflow
  12. 【浙江大学PAT真题练习乙级】1006 换个格式输出整数 (15分) 真题解析
  13. dtw算法 c语言实现,DTW算法的python实现
  14. Github 爆火!程序员疯抢的 Java 面试宝典(PDF 版)限时开源
  15. 算法导论第三版 第3章习题答案
  16. 苹果手机计算机怎么打分数,请问苹果手机计算器问题怎么处理的
  17. Seventh season eighteenth episode,Joey got an award??????
  18. AnySDK吉祥物征名活动开始啦!
  19. Doctype 作用? 严格模式与混杂模式-如何触发这两种模式,区分它们有何意义?
  20. 在m1/m2芯片的mac电脑上运行Stable Diffusion的全步骤

热门文章

  1. 2022-2028年中国儿童医疗行业深度调研及投资前景预测报告
  2. swig error : Unrecognized option -doxygen Ubuntu 安装 swig-3.0.12
  3. RSA、MD5等加密算法的区别和应用
  4. oss对象存储服务操作
  5. 解决Pycharm中SystemError报错
  6. SpringBoot-web开发(一): 静态资源的导入(源码分析)
  7. Compiler编译过程
  8. 人工智能AI Boosting HMC Memory Chip
  9. Jittor 的Op, Var算子
  10. 什么是视觉Visual SLAM