以下均是在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内存大小的计算的更多相关文章

  1. C++类所占内存大小计算

    C++类所占内存大小计算 说明:笔者的操作系统是32位的. class A {}; sizeof( A ) = ? sizeof( A ) = 1明明是空类,为什么编译器说它是1呢? 空类同样可以实例 ...

  2. 计算Java对象内存大小

    摘要 本文以如何计算Java对象占用内存大小为切入点,在讨论计算Java对象占用堆内存大小的方法的基础上,详细讨论了Java对象头格式并结合JDK源码对对象头中的协议字段做了介绍,涉及内存模型.锁原理 ...

  3. python 计算apache进程占用的内存大小以及占物理内存的比例

      目的:计算所有apache进程占用的内存大小以及占物理内存的比例: 思路:利用系统中/proc/meminfo的现有数据进行统计 1.pidof列出服务对应进程的PID [root@yanglih ...

  4. 一道题看懂OC的文件管理:NSFileManager,计算文件包含内存大小

    计算文件夹下所有文件的大小 // 查看错误信息 __autoreleasing NSError *error; // 文件管理对象 NSFileManager *manager = [NSFileMa ...

  5. Java对象的内存布局以及对象所需内存大小计算详解

    1. 内存布局 在HotSpot虚拟机中,对象的内存布局可以分为三部分:对象头(Header). 实例数据(Instance Data)和对齐填充(Padding). 1) 对象头(Header): ...

  6. Ehcache计算Java对象内存大小

    在EHCache中,可以设置maxBytesLocalHeap.maxBytesLocalOffHeap.maxBytesLocalDisk值,以控制Cache占用的内存.磁盘的大小(注:这里Off ...

  7. HDP3.1 中 YRAN 和 MR2 的内存大小配置的计算方式

    Container 是 YARN 中基本的处理单元,它是对内存.CPU等计算的封装.总的来说,每个core每块硬盘 分配2个 container,能获得较好的集群利用率. 1. 确定可用内存大小. 对 ...

  8. 【转】C/C++ struct/class/union内存对齐

    原文链接:http://www.cnblogs.com/Miranda-lym/p/5197805.html struct/class/union内存对齐原则有四个: 1).数据成员对齐规则:结构(s ...

  9. C/C++中struct/union/class内存对齐

    struct/union/class内存对齐原则有四个: 1).数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储 ...

随机推荐

  1. java使用jxls导出Excel

    jxls是基于POI的Excel模板导出导入框架.通过使用类似于jstl的标签,有效较少导出Excel的代码量. 1.pom <!-- https://mvnrepository.com/art ...

  2. HTML连载24-属性选择器(下)

    一.格式 标签[属性=值]:{属性:值:} 1.属性的取值是以什么开头的 attribute |= value(CSS2) attribute^=value(CSS3) 两者之间的区别:CSS2中只能 ...

  3. python-6-for循环及format三种用法

    前言 循环我们前面讲过了无限循环,那么for循环属于什么循环呢?显然就是有限循环: 另外格式化输出我们前面也讲过,但是format也能做到不一样的格式化输出.一起看看吧! 一.for 循环 1.fro ...

  4. CSS改变浏览器默认滚动条样式

    前言 最近总是看到某网站滚动条不是浏览器默认样式,而是自定义样式   比如我博客的滚动条,自定义滚动条样式和hover前后的效果 顿时来了兴致和有一个疑问,这是怎么实现的呢? 解决   注:经测试,目 ...

  5. Linux查找文件夹下包含某字符的所有文件

    Linux grep 命令用于查找文件里符合条件的字符串.grep 指令用于查找内容包含指定的范本样式的文件,如果发现某文件的内容符合所指定的范本样式,预设 grep 指令会把含有范本样式的那一列显示 ...

  6. 【题解】Dvoniz [COCI2011]

    [题解]Dvoniz [COCI2011] 没有传送门,只有提供了数据的官网. [题目描述] 对于一个长度为 \(2*K\) 的序列,如果它的前 \(K\) 个元素之和小于等于 \(S\) 且后 \( ...

  7. Mysql综述--数据是如何读存的?(2)

    页的结构 页是一种InnoDB管理存储空间的基本单位,它一般大小在16kb左右.实际上存在着许多不同类型的页,我们这次主要介绍的页是用来存储数据的,也叫做索引页. 接下来看看索引页的结构图: 比较重要 ...

  8. Enum.GetUnderlyingType(obj.GetType())

    Enum.GetUnderlyingType(obj.GetType())获取保存枚举值的数据类型:

  9. 如何利用 VisualStudio2019 遠端工具進行偵錯

    Hi 這次要來介紹 如何使用 Visual Studio 2019 遠端工具進行 Release 應用程式偵錯 首先我們先下載 2019 專用的遠端工具(這裡依照不同的 VisualStudio 版本 ...

  10. git和小乌龟在windows下安装

    一:所需软件 (1):git 下载地址:https://git-scm.com/download (2):TortoiseGit 下载地址:https://tortoisegit.org/downlo ...