[本节目标]
目前成都创新互联已为1000多家的企业提供了网站建设、域名、网站空间、网站托管、服务器租用、企业网站设计、贞丰网站维护等服务,公司将坚持客户导向、应用为本的策略,正道将秉承"和谐、参与、激情"的文化,与客户和合作伙伴齐心协力一起成长,共同发展。续: 把这个知识点单独列一篇博客是因为相对上一节, 这个知识点更加独立一些.
1. 类的对象大小的计算
问题: 这是一个简单的类, 但是这个类中即有成员变量, 又有成员函数, 那么这个类的大小是多少?
答案是一个字节. char _a的大小确实是一个字节, 那么PrintA()函数的大小去哪儿了呢, 难道函数不占空间么?
猜测一: 在类中的所有函数都以指针形式存放, 一个函数就是一个指针即4个字节或8个字节, 再加上各自的成员变量的类型大小, 以结构体内存规则对齐存放, 是这样么?
不是的, 每个对象中成员变量是不同的, 但是调用同一份函数, 什么意思呢, 假设Class A中有一个函数叫Add(), 接着Class A实例化了两个对象 object1 和object2 , 那么当你分别调用这两个函数中的Add()函数时, 这两个函数一样么? 其实你调用的是同一个函数. 如果按照猜测一的方式进行储存, 当一个类定义多个对象时, 每个对象中都在储存区中保存一份代码, 相同代码保存多次, 浪费空间!!!
猜测二: 类中只保存成员变量, 成员函数只保存一个函数名, 函数具体内容通过一个页表映射到存储区各个位置, 调用的时候再通过这个页表去找到具体的代码.
可以的, 这种存储方式在某些结构上正是如此应用的, 但是在类中,还不是这种方法, 此种方法暂略过不做讲解
猜测三: 类中只保存成员变量, 成员函数储存在公共代码区. 类中采用的方式正是猜测三, 接下去通过一段代码验证一下.
A1中有一个成员函数和一个成员变量char, 大小为1, 说明函数没存在对象i 中
A2中有一个成员变量char, 大小为1, 说明char是存在对象j 中得
A3是一个空类, 但为了给对象k占位, 也存了一个字节
结论: 一个类的大小, 实际就是该类中成员变量之和, 当然也要进行内存对齐, 注意空类的大小, 空类比较特殊, 占位一个字节
C语言结构体内存对齐规则 复习:
1. 第一个成员在与结构体偏移量为0 的地址处.
2. 其他成员变量要对其某个数字(对齐数)的整数倍的地址处.
对齐数 = 编译器默认的一个对齐数 与 该成员大小的的较小值. VS一般默认是8
3. 结构体总大小为: 大对齐数的整数倍, 如果不够,在计算时需要补齐
4. 如果是嵌套结构体, 嵌套的结构体对齐到自己的大对齐数的整数倍 处, 结构体的整体大小是所有大对齐数的整数倍
面试题:
1. 结构体怎么对齐? 为什么要进行内存对齐
直接上代码,用图说话吧
这里如果不考虑结构体对齐规则的话, 直接计算结构体大小, 应该是int + char + int + int = 4+1+4 = 10.
当然, 结果肯定是不对的. 那么实际情况应该是怎么样的呢?
这里如果没理解清楚的话, 那我们继续上图, 用图说话.
看官们可以自行验证一下.
2. 如何让结构体按照指定的对齐参数进行对齐?
#pragma pack x (x为指定对齐数值) 举例如果x是4, 那么统一按照4个字节进行对齐,
还是上面那个例子
按照之前计算应该为16个字节大小, 可是实际结果为10个字节,怎么算的呢?
对齐数现在为1, 即不需要为了对齐而进行占位了. 1 + 4 + 1+4 = 10
如果改成#pragma pack(2)呢?
相信看到这里大家对于结构体对齐规则肯定搞懂了 , 那么嵌套结构体应该如何计算呢?
也非常简单, 首先肯定是先计算最里面的那个结构体大小 . 然后再确定对齐数是多少,
这种嵌套结构体的大对齐数是取其成员大类型的大小, 如下面代码
#include#includestruct S1 {
char a;// 0
double b;// 8-15
short c[2];//16-19,因为double的8比short的2大,引用规则一
//共24
};
struct S2 {
struct S1 a;// , 0-23
int b;//24-27
char c;//28
// 最后按S1的大类型double的8字节对齐,因为double比S2的int和char字节数都大,最后
//整个S2按照8字节对齐
};
int main() {
using namespace std;
cout<< sizeof(S1)<< " "<< sizeof(S2)<< endl;
}
就是max(sizeof(struct S1),sizeof(max_type_of_S2))
补充:关于#pragma pack(x)
编译器会自动优化, 比如说结构体中大的成员变量是int, 4个字节 , 你指定8 个字节对齐, 那么是无效的, 编译器判断大的成员变量就是4个字节,将以4个字节规则进行对齐.
3. 什么是大小端? 如何测试某台机器是大端还是小端, 有没有遇到过要考虑大小端的场景
大小端是计算机储存数据的一种格式, 大端是数据的低地址存在高位, 小端是数据的低地址存在低位, 可以用代码测试
解析 : int类型i 的值是 1 , 如果是大端存储 就是 : 0000 0000 0000 0001 , 如果是小端存储就是
1000 0000 0000 0000 . 取地址i , 然后强制转化成char* 类型, 再解引用, 因为char*类型解引用只访问1个字节, 赋值给c, 那么此时c如果是1就是小端模式, 如果是0就是大端模式
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧