C++内存对齐总结
大家都知道,C++空类的内存大小为1字节,为了保证其对象拥有彼此独立的内存地址。非空类的大小与类中非静态成员变量和虚函数表的多少有关。
而值得注意的是,类中非静态成员变量的大小与编译器内存对齐的设置有关。
成员变量在类中的内存存储并不一定是连续的。它是按照编译器的设置,按照内存块来存储的,这个内存块大小的取值,就是内存对齐。
一、引入问题。
#include<iostream>
using namespace std;
class test {
private : char c='';//1byte
int i;//4byte
short s=;//2byte
}; int main(){
cout << sizeof(test) << endl;
return ;
}
输出:12
class test2 {
private:
int i;//4byte
char c = '';//1byte
short s = ;//2byte
}; int main(){
cout << sizeof(test2) << endl;
return ;
}
输出:8
我们可以看到。类test和test2的成员变量完全一样,只是定义顺序不一样,却造成了2个类占用内存大小不一样。而这就是编译器内存对齐的缘故。
二、规则
1、第一个数据成员放在offset为0的地方,以后每个数据成员的对齐按照#pragma pack指定的数值和这个数据成员自身长度中,比较小的那个进行。
2、在数据成员完成各自对齐之后,类(结构或联合)本身也要进行对齐,对齐将按照#pragma pack指定的数值和结构(或联合)最大数据成员长度中,比较小的那个进行。
很明显#pragma pack(n)作为一个预编译指令用来设置多少个字节对齐的。值得注意的是,n的缺省数值是按照编译器自身设置,一般为8,合法的数值分别是1、2、4、8、16。
即编译器只会按照1、2、4、8、16的方式分割内存。若n为其他值,是无效的。
三、问题分析
(1)对于类test的内存空间是这样的:
内存分配过程:
1、char和编译器默认的内存缺省分割大小比较,char比较小,分配一个字节给它。
2、int和编译器默认的内存缺省分割大小比较,int比较小,占4字节。只能空3个字节,重新分配4个字节。
3、short和编译器默认的内存缺省分割大小比较,short比较小,占2个字节,分配2个字节给它。
4、对齐结束类本身也要对齐,所以最后空余的2个字节也被test占用。
(2)对于类test2的内存空间是这样的:
1、int和编译器默认的内存缺省分割大小比较,int比较小,占4字节。分配4个字节给int。
2、char和编译器默认的内存缺省分割大小比较,char比较小,分配一个字节给它。
3、short和编译器默认的内存缺省分割大小比较,short比较小,此时前面的char分配完毕还余下3个字节,足够short的2个字节存储,所以short紧挨着。分配2个字节给short。
4、对齐结束类本身也要对齐,所以最后空余的1个字节也被test占用。
(3)使用#pragma pack(n)
#include<iostream>
using namespace std;
#pragma pack(1)//设定为 1 字节对齐
class test {
private : char c='';//1byte
int i;//4byte
short s=;//2byte
}; class test2 {
private:
int i;//4byte
char c = '';//1byte
short s = ;//2byte
};
int main(){
cout << sizeof(test) << endl;
cout << sizeof(test2) << endl;
return ;
}
输出:
可以看到,当我们把编译器的内存分割大小设置为1后,类中所有的成员变量都紧密的连续分布。
至此,C++内存对齐总结已经差不多了。想要更多了解C++对象内存分配推荐陈浩的2篇文章:
http://blog.csdn.net/haoel/article/details/3081328
和http://blog.csdn.net/haoel/article/details/1948051
陈浩大神写的太透彻了。
参考:http://www.cppblog.com/snailcong/archive/2009/03/16/76705.html
http://www.jb51.net/article/45406.htm
最新文章
- 一年之计在于春,2015开篇:PDF.NET SOD Ver 5.1完全开源
- 《Entity Framework 6 Recipes》中文翻译系列 (30) ------ 第六章 继承与建模高级应用之多对多关联
- WPF 自定义雷达图
- effective java —— 终结方法守卫者
- C#中DateTime.Now.ToString()
- 使用 archetype插件创建maven目录结构
- python ljust,rjust,center,zfill对齐使用方法
- MVC Area Usage
- assert的用处
- leetcode 27
- 简单图片banner轮播
- JavaScript 的setAttribute兼容性解决
- 有利于SEO的DIV+CSS规范小结
- Selenium模拟JQuery滑动解锁
- (转)从史上八大MySQL宕机事故中学到的经验
- navicat导入.sql文件
- springmvc 项目完整示例04 整合mybatis mybatis所需要的jar包 mybatis配置文件 sql语句 mybatis应用
- svn各种表示含义及解决
- 将caj文件转化为pdf文件进行全文下载脚本(ubuntu下亲测有用)
- 一个可用来记录Isilon各个节点的CPU,网络,磁盘性能的命令
热门文章
- C语言 &#183; 矩形面积交
- Java基础Map接口+Collections
- 菜鸟学Struts2——零配置(Convention )
- android 使用Tabhost 发生could not create tab content because could not find view with id 错误
- 卡片抽奖插件 CardShow
- 如何定位Oracle数据库被锁阻塞会话的根源
- Java FtpClient 实现文件上传服务
- setCapture、releasCapture 浅析
- interpreter(解释器模式)
- PHP 设计模式概述