资讯

精准传达 • 有效沟通

从品牌网站建设到网络营销策划,从策略到执行的一站式服务

C++入门03-创新互联

类和对象(上)

[本节目标]

目前成都创新互联已为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元起,快前往官网查看详情吧


分享标题:C++入门03-创新互联
浏览地址:http://cdkjz.cn/article/csohds.html
多年建站经验

多一份参考,总有益处

联系快上网,免费获得专属《策划方案》及报价

咨询相关问题或预约面谈,可以通过以下方式与我们联系

大客户专线   成都:13518219792   座机:028-86922220