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的地方,以后每个数据成员存储 ...
随机推荐
- 字节跳动笔试题:1. 小于N的质数数量;2. 逆时针二维数组;3. 判断a+b>c
1. 小于N的质数数量 import java.util.Scanner; /** * 计算小于N的质数数量 * @author Turing * */ public class Main4 { pu ...
- 解决node fs.writeFile 生成csv 文件乱码问题
解决node fs.writeFile 生成csv 文件乱码问题: fs.writeFile('xxx.csv', '\ufeff' + 要传入的数据, {encoding: 'utf8'}); \u ...
- 【django json.dumps 报错】 datetime.datetime is not JSON serializable
django 中,json.dumps 无法直接转译 datetime 类型的值. 找了无数方法,找到一个最优.最简洁的解决办法: json.dumps(results, indent=4, sort ...
- 【mysql】修改mysql数据库密码
修改mysql数据库密码 操作系统:Linux centos7 数据库:mysql5.7 一.在已知MYSQL数据库的ROOT用户密码的情况下,修改密码 1.在Linux命令行,使用mysqladmi ...
- spring 注解AOP
aspectAnnotation的切面信息,加到了AnnotationAwareAspectJAutoProxyCreator的advisorsCache属性里面去了. 解析annotationSe ...
- WPF 有任何Focus问题,就找 Keyboard_Navigation
牛牛的博客 https://www.cnblogs.com/smallidea/p/3412699.html 参照官网教程: https://docs.microsoft.com/en-us/dotn ...
- Python - 错误和异常 - 第十九天
Python 错误和异常 作为 Python 初学者,在刚学习 Python 编程时,经常会看到一些报错信息,在前面我们没有提及,这章节我们会专门介绍. Python 有两种错误很容易辨认:语法错误和 ...
- ASP.NET Core MVC 之依赖注入 View
ASP.NET Core 支持在试图中使用依赖注入.这将有助于提供视图专用的服务,比如本地化或者仅用于填充视图元素的数据.应尽量保持控制器和视图之间的关注点分离.视图所显示的大部分数据应该从控制器传入 ...
- 深入浅出JVM的锁优化案例
锁优化 适应性自旋(Adaptive Spinning) 线程阻塞的时候,让等待的线程不放弃cpu执行时间,而是执行一个自旋(一般是空循环),这叫做自旋锁. 自旋等待本身虽然避免了线程切换的开销,但它 ...
- ztree选父不选子选子不选父
var setting = { data: { simpleData: { enable: true } } ,check: { enable: true , chkStyle: 'checkbox' ...