很多C++书籍中都介绍过,一个Class对象需要占用多大的内存空间。最权威的结论是:

*非静态成员变量总合。(not static)

*加上编译器为了CPU计算,作出的数据对齐处理。(c语言中面试中经常会碰到内存对齐的问题)

*加上为了支持虚函数(virtual function),产生的额外负担。

下面给出几个程序来看一下:

#include <iostream>
#include <cstdio>
#include <string>
using namespace std;
class Car1{
}; void fun1(void)
{
int size =0;
Car1 objCar;
size = sizeof(objCar);
printf("%s is %d\n","Class Car1 Size",size);
} class Car2{
private:
int nLength;
int nWidth;
};
void fun2(void)
{
int size = 0;
Car2 objCar;
size = sizeof(objCar);
printf("%s is %d\n","Class Car2 Size",size);
} class Car3{
private:
int nLength;
int nWidth;
static int sHight;
};
void fun3(void)
{
int size =0;
Car3 objCar;
size =sizeof(objCar);
printf("%s is %d\n","Class Car3 Size",size);
} class Car4{
private:
char chLogo;
int nLength;
int nWidth;
static int sHigh;
};
void fun4(void)
{
int size =0;
Car4 objCar;
size = sizeof(objCar);
printf("%s is %d\n","Class Car4 Size",size);
} class Car5{
public:
Car5(){};
~Car5(){};
public:
void Fun(){};
}; void fun5(void)
{
int size =0 ;
Car5 objCar;
size = sizeof(objCar);
printf("%s is %d\n","Class Car5 Size",size);
} class Car6{
public:
Car6(){};
~Car6(){};
public:
void Fun(){};
private:
int nLength;
int nWidth;
};
void fun6(void)
{
int size = 0;
Car6 objCar;
size = sizeof(objCar);
printf("%s is %d\n","Class Car6 Size",size);
} class Car7{
public:
Car7(){};
virtual ~Car7(){};
public:
void Fun(){};
};
void fun7(void)
{
int size = 0;
Car7 objCar;
size = sizeof(objCar);
printf("%s is %d\n","Class Car7 Size",size);
} class Car8{
public:
Car8(){};
virtual ~Car8(){};
public:
void Fun(){};
virtual void Fun1(){}
};
void fun8(void)
{
int size = 0;
Car8 objCar;
size = sizeof(objCar);
printf("%s is %d\n","Class Car8 Size",size);
} int main()
{
fun1();
fun2();
fun3();
fun4();
fun5();
fun6();
fun7();
fun8();
}

编译:g++ memAlign.cpp -o memAlign

输出结果:

Class Car1 Size is 1
Class Car2 Size is 8
Class Car3 Size is 8
Class Car4 Size is 12
Class Car5 Size is 1
Class Car6 Size is 8
Class Car7 Size is 8
Class Car8 Size is 8

ps:上述编译环境是在mac os下的g++

下面我们具体来分析一下这几个情况:

1、空类、单一继承的空类、多重继承的空类所占空间大小为:1(字节,下同);

2、一个类中,虚函数本身、成员函数(包括静态与非静态)和静态数据成员都是不占用类对象的存储空间的;

3、因此一个对象的大小≥所有非静态成员大小的总和;

4、当类中声明了虚函数(不管是1个还是多个),那么在实例化对象时,编译器会自动在对象里安插一个指针vPtr指向虚函数表VTable;

5、虚继承的情况:由于涉及到虚函数表和虚基表,会同时增加一个(多重虚继承下对应多个)vfPtr(virtual function table)指针指向虚函数表vfTable和一个vbPtr(virtual base pointer)指针指向虚基表vbTable,这两者所占的空间大小为:8(或8乘以多继承时父类的个数);

6、在考虑以上内容所占空间的大小时,还要注意编译器下的“补齐”padding的影响,即编译器会插入多余的字节补齐;(请参考《c和指针》)

7、类对象的大小=各非静态数据成员(包括父类的非静态数据成员但都不包括所有的成员函数)的总和+ vfptr指针(多继承下可能不止一个)+vbptr指针(多继承下可能不止一个)+编译器额外增加的字节。

参考:C++虚函数工作原理和(虚)继承类的内存占用大小计算

在VC 6.0中,结果是

Class Car1 Size is 1
Class Car2 Size is 8
Class Car3 Size is 8
Class Car4 Size is 12
Class Car5 Size is 1
Class Car6 Size is 8
Class Car7 Size is 4
Class Car8 Size is

主要的不同点是:在Car7和Car8,在VC 6.0中虚函数指针占用4个字节,在gcc编译器中占用8个字节。

        也可以换一种说法是virtual函数指针在VC下以4字节对齐,在gcc下是8字节对齐,这样解释就比较清楚了。

二、编程实现成员在类或结构体中的偏移量

代码如下所示:

 1 #include <cstdio>
2 #include <iostream>
3 #define pos(type,member) (&((type *)0)->member)
4
5 class car{
6 public:
7 car(){}
8 ~car(){}
9 public:
10 virtual void fun(){}
11 private:
12 int c;
13 public:
14 void print()
15 {
16 printf("%x\n",pos(car,c));
17 }
18 };
19
20 int main()
21 {
22 struct Node{
23 int a ;
24 char b;
25 int c;
26 };
27 car objCar;
28 // printf("%x\n",&((struct Node *)0)->b);
29 printf("%x\n",pos(struct Node,b));
30 printf("%x\n",pos(struct Node,c));
31 // printf("%x\n",pos(class car,c));
32 objCar.print();
33 return 0;
34 }

其中关键的是找到函数能够实现计算成员在类中的偏移量,这里用了宏来实现的。

#define pos(type,member) (&((type *)0)->member)

(从地址0开始的一个type结构体或者类,其成员的地址就是成员所在类或结构体的偏移量)

上述程序的输出结果就是:4 8 8

c++中类对象的内存对齐的更多相关文章

  1. 重磅硬核 | 一文聊透对象在 JVM 中的内存布局,以及内存对齐和压缩指针的原理及应用

    欢迎关注公众号:bin的技术小屋 大家好,我是bin,又到了每周我们见面的时刻了,我的公众号在1月10号那天发布了第一篇文章<从内核角度看IO模型的演变>,在这篇文章中我们通过图解的方式以 ...

  2. 关于C++内存对齐

    关于C++内存对齐 C++11从标准层面引入了一些和内存对齐相关的特性,标准库也增加了对应的组件,这里稍微总结一下. 取得某个类型的对齐值 C++中的Object(对象)是指一块满足以下条件的内存区域 ...

  3. NumPy-快速处理数据--ndarray对象--多维数组的存取、结构体数组存取、内存对齐、Numpy内存结构

    本文摘自<用Python做科学计算>,版权归原作者所有. 上一篇讲到:NumPy-快速处理数据--ndarray对象--数组的创建和存取 接下来接着介绍多维数组的存取.结构体数组存取.内存 ...

  4. C++内存对齐总结

    大家都知道,C++空类的内存大小为1字节,为了保证其对象拥有彼此独立的内存地址.非空类的大小与类中非静态成员变量和虚函数表的多少有关. 而值得注意的是,类中非静态成员变量的大小与编译器内存对齐的设置有 ...

  5. C/C++: C++位域和内存对齐问题

    1. 位域: 1. 在C中,位域可以写成这样(注:位域的数据类型一律用无符号的,纪律性). struct bitmap { unsigned a : ; unsigned b : ; unsigned ...

  6. JVM中,对象在内存中的布局

    在hotSpot虚拟机中,对象在内存中的布局可以分成对象头.实例数据.对齐填充三部分. 对象头:主要包括: 1.对象自身的运行行元数据,比如哈希码.GC分代年龄.锁状态标志等,这部分长度在32位虚拟机 ...

  7. 内存对齐 和 sizeof小结

    数据对齐(内存对齐)指该数据所在的地址必须是该数据长度的整数倍.X86CPU能直接访问对齐的数据,当它试图访问未对齐的数据时,会在内部进行一系列的调整,降低运行速度.数据对齐一般出现在结构体和类中,在 ...

  8. C语言再学习之内存对齐

    昨天看Q3的代码,看到有个_INTSAIZEOF的宏,着实晕了一阵.一番google后,终于明白,这个宏的作用是求出变量占用内存空间的大小,先看看_INTSAIZEOF的定义吧: #define _I ...

  9. C结构体中数据的内存对齐问题

    转自:http://www.cnblogs.com/qwcbeyond/archive/2012/05/08/2490897.html 32位机一般默认4字节对齐(32位机机器字长4字节),64位机一 ...

随机推荐

  1. React 实践项目 (一)

    React在Github上已经有接近70000的 star 数了,是目前最热门的前端框架.而我学习React也有一段时间了,现在就开始用 React+Redux 进行实战! 项目代码地址:https: ...

  2. Spring+Mybatis配置

    Spring+Mybatis配置 之前做项目的时候用到了spring+mybatis框架,一直想抽空整理一下 Mybatis: mybatis是支持普通 SQL查询,存储过程和高级映射的优秀持久层框架 ...

  3. eclipse打开时提示:failed to create the java virtual machine

    Eclipse打开时提示: failed to create the java virtual machine 原因:C盘空间不够   编辑删除 处理:1.用金山清理临时文件: 2.用金山手机卫士连接 ...

  4. Jenkins设置Master/Slave

    说明:通过master/slave模式,可以在master节点上统一管理其他slave节点. 下面说明一步步实现master/slave模式. 第一步:以管理员登录jenkins.点击"系统 ...

  5. Unreal Engine 4 Radiant UI 插件入门教程(二)

    本篇章前提要求:在UE4上安装了Radiant UI插件.如果没有安装,请找其它教程(或者是笔者的其它的教程,目前正在写). 本教程的目的:探讨如何从网页元素中调用蓝图中的内容: 第一步: 写一个网页 ...

  6. 通过ALM OTA API获取test case的信息,并上传测试结果到test set中

    ALM提供了OTA接口,可以用来获取和上传测试数据到ALM.比如获取Test case的step信息.上传测试结果到test instance. 在ALM的Help中可以下载相关文档,这里以ALM11 ...

  7. Linux 教程 技巧集

    Linux 终端操作技巧 CTRL + U - 剪切光标前的内容 CTRL + K - 剪切光标至行末的内容 CTRL + Y - 粘贴 CTRL + E - 移动光标到行末 CTRL + A - 移 ...

  8. [asp.net mvc 奇淫巧技] 05 - 扩展ScriptBundle,支持混淆加密javascript

    一.需求: 在web开发中,经常会处理javascript的一些问题,其中就包括js的压缩,合并,发布版本以及混淆加密等等问题.在asp.net 开发中我们使用ScriptBundle已经可以解决ja ...

  9. Gym 100952 D. Time to go back(杨辉三角形)

    D - Time to go back Gym - 100952D http://codeforces.com/gym/100952/problem/D D. Time to go back time ...

  10. 以图像分割为例浅谈支持向量机(SVM)

    1. 什么是支持向量机?   在机器学习中,分类问题是一种非常常见也非常重要的问题.常见的分类方法有决策树.聚类方法.贝叶斯分类等等.举一个常见的分类的例子.如下图1所示,在平面直角坐标系中,有一些点 ...