struct和class内存大小的计算
以下均是在VS2017下的结果
结构体内存大小的计算:
用例一:
#include<stdio.h>
union ss
{
int a;
char b;
};
struct MyStruct
{
int temp1;//4个字节
char temp2;//一个字节,补齐3个字节
ss aa;//4个字节
char temp3;//一个字节
char temp4;//一个字节,补齐两个字节
};
int main()
{
printf("%d", sizeof(MyStruct));
return 0;
}
输出 16
解析:对齐规则是按照成员的声明顺序,依次安排内存,对齐字节数为最大成员变量的字节大小,偏移量为最大成员变量的字节数的整数倍,在这个程序中对齐字节数为4,计算步骤如下:
首先是temp1 四个字节,temp2 一个字节,还剩3个字节,因为后面是aa 4个字节,可以自己对齐,所以temp2需要补齐3个字节, temp3 一个字节,temp4一个字节,对齐是4个字节,还剩2个字节需要补齐。所以总共是16个字节。
#include<stdio.h>
union ss
{
int a;
double b;
};
struct MyStruct
{
int temp1;//4个字节
char temp2;//1个字节,对齐是8个字节,还需3个字节补齐
ss aa;//8个字节
char temp3;//1个字节
short temp4;//2个字节,补齐还需要5个字节
};
int main()
{
printf("%d", sizeof(MyStruct));
return 0;
}
输出结果为 24
#include<stdio.h>
union ss
{
int a;
double b;
}; struct student
{
int name;
char sex;
double num; };
struct MyStruct
{
int temp1;//4个字节
char temp2;//1一个字节,补齐3个字节
ss aa;//8个字节
char temp3;//一个字节
short temp4;//2个字节,补齐5个字节
student people;//16个字节
};
int main()
{
printf("%d", sizeof(MyStruct));
return 0;
}
结果为 40
解析:此时需要注意的是,对齐字节数8个字节,而不是16个字节。student people 对象内部先进行一次对齐,然后如果如果是外面对齐字节数的整数倍就不需要
再进行对齐了,如果不是就需要再次进行对齐。
下面的是需要二次对齐的程序:
#include<stdio.h>
struct MyStruct
{
char temp1;
char temp2;
};
struct student
{
int name;//4个字节
char sex;//1个字节
MyStruct aa;//2个字节
char temp;//1个字节 };
int main()
{
printf("%d", sizeof(student)); }
输出为 8
#include<stdio.h>
union ss
{
int a;
double b;
}; struct student
{
//int name;
//char sex;
int num; };
struct MyStruct
{
int temp1;//4个字节
char temp2;//1一个字节,补齐3个字节
ss aa;//8个字节
char temp3;//1个字节
short temp4;//2个字节
student people;//4个字节,补齐一个字节
};
int main()
{
printf("%d", sizeof(MyStruct));
return 0;
}
输出结果为:24
总结,在一个结构体中有另一个结构体的对象时,对齐字节数与这个结构体对象的字节数无关,只与结构体中的成员变量和union 有关。
类的内存大小的计算
只含有成员函数的类和空类的内存大小:
#include<iostream>
using namespace std;
class student
{
public:
student()
{
cout << "构造函数" << endl;
}
//void fun();
};
int main()
{
cout << sizeof(student) << endl;
return 0;
}
运行结果: 1
解析:如果是空类也会输出1。如果一个类只含有成员函数没有成员变量或者虚函数,类的大小都是1。如果含有静态成员变量或者是静态成员函数,也会是1,因为静态成员变量和静态成员函数是类的所有对象共享的,它并不存放在一个实例化对象中
为什么空类也会是1呢?
所谓类的实例化就是在内存中分配一块地址,每一个实例在内存中都有独一无二的地址,而了到达这个效果,编译器往往会给一个空类隐含的增加一个字节,这样实例化出来的每一个空类的对象都会得到一个独一无二的地址。如果空类的大小是0的话,那么实例化出来的所有空类对象都是在同样一个内存地址上,就相当于同一个对象,这不是我们想要的。
只含有静态成员函数和静态成员变量的类的内存大小:
#include<iostream>
using namespace std;
class student
{
static int b;
static void func();
};
int main()
{
cout << sizeof(student) << endl;
return 0;
}
输出结果:1
解析:因为静态成员变量和静态成员函数都是类的所有对象共享的,静态成员变量存放在全局存储区,静态成员变量和静态成员函数在编译时就已经在全局区分配的内存。
含有成员变量的类的内存大小:
#include<iostream>
using namespace std;
class student
{
int a;//4个字节
char c;//1个字节,对齐,需要补齐3个字节
static int b;
static void func();
};
int main()
{
cout << sizeof(student) << endl;
return 0;
}
输出为 8
含有虚函数的类的内存大小:
#include<iostream>
using namespace std;
class student
{
int a;//4个字节
char c;//1一个字节,对齐,补齐3个字节
static int b;
public:
static void func();
virtual void fly();//4个字节
};
int main()
{
cout << sizeof(student) << endl;
return 0;
}
输出为 12
解析:虚函数会产生一个虚函数指针,指针大小为4个字节,虚函数指针指向虚函数表。
但是并不是每一个虚函数都会产生一个虚函数指针,同一个类中的所有虚函数只会产生一个虚函数指针。
继承下的类的内存大小:
#include<iostream>
using namespace std;
class student
{
int a;
char c;
static int b;
public:
static void func();
virtual void fly();
};
class student1: public student
{
int d;//4个字节
};
int main()
{
cout << sizeof(student1) << endl;
return 0;
}
输出 16
解析:派生类会继承父类的成员变量和虚函数等,所以子类的内存大小是在父类的内存大小的基础上加上自己增加的内存大小。
父类和子类中都有虚函数的类的内存大小:
#include<iostream>
using namespace std;
class student
{
int a;
char c;
static int b;
public:
static void func();
virtual void fly();
};
class student1: public student
{
int d;
public:
void fly();
virtual void eat();
};
int main()
{
cout << sizeof(student1) << endl;
return 0;
}
输出为:16
问题:子类声明了一个虚函数且该虚函数是父类中没有的虚函数为什么子类没有新产生一个虚函数指针。
这个涉及到内存布局问题,首先是基类产生了一个虚函数指针,这个虚函数指针会指向虚函数表,表中存放的是基类的虚函数。子类也会继承到这个虚函数指针,虚函数指针指向虚函数表,表中先是存放基类的虚函数,再存放子类的基函数,如果子类重载了父类的某些虚函数,那么新的虚函数将虚函数表中父类对应的虚函数覆盖
虚继承——空类
#include<iostream>
using namespace std;
class student
{ };
class student1: virtual student
{ };
int main()
{
cout << sizeof(student1) << endl;
return 0;
}
输出结果为 4
虚继承——基类含有虚函数指针,子类不含有虚函数指针
#include<iostream>
using namespace std;
class student
{
int a;
char c;
//static int b;
public:
//static void func();
virtual void fly();
};
class student1: virtual student
{
int d;
public:
void fly();
//virtual void eat();
};
int main()
{
cout << sizeof(student1) << endl;
return 0;
此时输出为:20
解析:因为虚继承会再产生一个虚函数指针,去指向对应的基类,防止子类继承多个一样的基类,造成资源浪费
虚继承:子类和父类都有虚函数
#include<iostream>
using namespace std;
class student
{
int a;
char c;
//static int b;
public:
//static void func();
virtual void fly();
};
class student1: virtual student
{
int d;
public:
void fly();
virtual void eat();
};
int main()
{
cout << sizeof(student1) << endl;
return 0;
}
输出:24
解析:此时是子类声明的虚函数是父类没有的,则此时子类会再产生一个虚函数指针,如果此时子类的所有虚函数都是继承自基类的,则不会产生虚函数指针。
struct和class内存大小的计算的更多相关文章
- C++类所占内存大小计算
C++类所占内存大小计算 说明:笔者的操作系统是32位的. class A {}; sizeof( A ) = ? sizeof( A ) = 1明明是空类,为什么编译器说它是1呢? 空类同样可以实例 ...
- 计算Java对象内存大小
摘要 本文以如何计算Java对象占用内存大小为切入点,在讨论计算Java对象占用堆内存大小的方法的基础上,详细讨论了Java对象头格式并结合JDK源码对对象头中的协议字段做了介绍,涉及内存模型.锁原理 ...
- python 计算apache进程占用的内存大小以及占物理内存的比例
目的:计算所有apache进程占用的内存大小以及占物理内存的比例: 思路:利用系统中/proc/meminfo的现有数据进行统计 1.pidof列出服务对应进程的PID [root@yanglih ...
- 一道题看懂OC的文件管理:NSFileManager,计算文件包含内存大小
计算文件夹下所有文件的大小 // 查看错误信息 __autoreleasing NSError *error; // 文件管理对象 NSFileManager *manager = [NSFileMa ...
- Java对象的内存布局以及对象所需内存大小计算详解
1. 内存布局 在HotSpot虚拟机中,对象的内存布局可以分为三部分:对象头(Header). 实例数据(Instance Data)和对齐填充(Padding). 1) 对象头(Header): ...
- Ehcache计算Java对象内存大小
在EHCache中,可以设置maxBytesLocalHeap.maxBytesLocalOffHeap.maxBytesLocalDisk值,以控制Cache占用的内存.磁盘的大小(注:这里Off ...
- HDP3.1 中 YRAN 和 MR2 的内存大小配置的计算方式
Container 是 YARN 中基本的处理单元,它是对内存.CPU等计算的封装.总的来说,每个core每块硬盘 分配2个 container,能获得较好的集群利用率. 1. 确定可用内存大小. 对 ...
- 【转】C/C++ struct/class/union内存对齐
原文链接:http://www.cnblogs.com/Miranda-lym/p/5197805.html struct/class/union内存对齐原则有四个: 1).数据成员对齐规则:结构(s ...
- C/C++中struct/union/class内存对齐
struct/union/class内存对齐原则有四个: 1).数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储 ...
随机推荐
- Python爬取拉勾网招聘信息并写入Excel
这个是我想爬取的链接:http://www.lagou.com/zhaopin/Python/?labelWords=label 页面显示如下: 在Chrome浏览器中审查元素,找到对应的链接: 然后 ...
- 不支持中国移动的N79频段,红米K30是假5G手机么?影响有多大?
原文:https://mparticle.uc.cn/article.html?uc_param_str=frdnsnpfvecpntnwprdssskt&btifl=100&app= ...
- python命令行解析函数
sys.argv 在终端运行python 1.py hahah import sys print(sys.argv) # ['1.py', 'hahah'] argparse Python的命令行解析 ...
- 海边拾贝-B-优秀博客/网站
记下若干优秀博客,方便后期检索.会不定期更新: 优秀的程序员,从使用Github开始:https://help.github.com/en/github/managing-your-work-on-g ...
- Jmockit 构造函数与初始代码块
from Jmockit 中文网 http://jmockit.cn/showArticle.htm?channel=4&id=14 有些编写不良好的类的构造函数,初始代码块,静态代码块存在大 ...
- 造轮子ArrayList
这篇博客实现一个简单的ArrayList集合.博客里的代码首先根据自己的想法实现,在走不动的情况下会去参考JDK源代码.所以阅读本文,不要抱着跟JDK源码对比的心态.于我个人而言,国庆期间,纯属娱乐. ...
- Composer 的安装
最近在家休息了两个月,本来打算看看书,结果和朋友做了个小项目.项目也差不多接近尾声了,就准备找工作了,朋友推荐我去他们公司做事,不过是使用 PHP 进行开发了.我这一年来使用 Java 进行开发,今后 ...
- 简述vue props和非props的2个特性
props的2个特性 ①:父组件通过属性的方式传值(比如下面截图中的content)给子组件,content不会显示在DOM节点中 ②:父组件向子组件传递值 ...
- Vue.js 源码分析(二十四) 高级应用 自定义指令详解
除了核心功能默认内置的指令 (v-model 和 v-show),Vue 也允许注册自定义指令. 官网介绍的比较抽象,显得很高大上,我个人对自定义指令的理解是:当自定义指令作用在一些DOM元素或组件上 ...
- laravel报错:SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '0' for key 'PRIMARY' (SQL: insert into `cart` (`uid`, `gid`, `gname`, `price`) values (3, 21, 夏季日系复古工装短袖衬衫男士印花潮流宽松五分
原因:要操作的数据表id没有设置自增,导致出现id为0的情况 解决方法:给该数据表的id字段设置自增