C++ 类大小分析

数字麦克风PDM信号采集与STM32 I2S接口应用(二) 在使用STM32的数字麦克风I2S接口时,计算采样率让人头疼,芯片手册上没有明确的说法,而手册上的计算方法经过测试却和实验不符。借助搜索引擎,大部分资料都是来自于开发板卖家或开发板论坛,主要是咪头采集然后配置WM89系列解码芯片,然后配合FatFS、MP3解码等模式,主要是讲解I2S录音、存储、放音等。外文资料得到的也寥寥无几,也没有找到讲解STM32数字麦克风配置、计算的文档。加上网上资料转载、抄袭、浅尝辄止的笔记教程,这些更是让检索大海捞针,过程艰辛一言难尽,有些网文三言两语抑或作者都没有搞清楚随手一写 阅读详情

以下测试代码的运行环境:

Ubuntu 16.04.4 LTS

gcc version 4.8.5

x64

  • 空类、单一继承的空类、多重继承的空类所占空间大小为:1(字节)。

       实例在内存中都有一个独一无二的地址,为了达到这个目的,编译器往往会给一个空类隐含的加一个字节,这样空类在实例化后在内存得到了独一无二的地址

  • 一个类中,虚函数本身、成员函数(包括静态与非静态)和静态数据成员都是不占用类对象的存储空间。

      类中如果有虚函数,那么该类对象会生成一张虚函数表,然后编译器会生成一个指向该虚表的指针vptr(virtual table pointer),该指针占用存储空间,具体下面虚函数会讲解,静态数据成员存放的在静态存储区,跟类对象存储空间不一样。

  • 为了优化存取效率,通常都会遵守内存对齐原则。

     通俗的理解是,类中最长的数据成员作为对齐原则,从其内部"最宽基本类型成员"的整数倍地址开始存储。比如类中有 char、int、float、double等元素,那么类应该从8的整数倍开始存储。

例如:

class AA{

public:

    char i;

    char j;

    double k;

};

int main()
{
    cout<<"size = "<<sizeof(AA)<<endl;
    return 0;
}

输出:16

该类大小等于数据大小之和,由于该类的“最宽”数据类型为double,所以按照8的整数倍进行存储,这里的计算方式:1+1+(6)+8 = 16.

注释:上面计算方法中的“(6)”是内存补齐,编译器自动处理的。之后的计算类似这样都表示内存补齐。

注意,如果数据的摆放顺序不一样,则类的大小也是有区别的:

class AA{

public:

    char i;

    double j;

    char k;

};

int main()
{
    cout<<"size = "<<sizeof(AA)<<endl;
    return 0;
}

输出:24

类中的数据成员是按照顺序进行摆放的,所以计算方式:1+(7)+8+1+(7) = 24

  • 虚函数,有虚函数的类有个virtual table(虚函数表),里面包含了类的所有虚函数,类中有个virtual table pointers,通常成为vptr指向这个virtual table。

一个类里边无论一个或者多个虚函数,都只有一个vptr,只要有一个虚函数,类中肯定会生成一张虚函数表vtable,表中保存的就是每个虚函数的地址。vptr指向vtable,然后在vtable中找到对应的虚函数。

class AA{
public:
    char i;
    int j;
    int k;
    virtual void func();
    virtual ~AA();
};

输出:24

注意,这里也有一个坑,由于测试环境是gcc version 4.8.5,ubuntu 系统 64位,所以虚函数指针vptr是8个字节,如果系统是32位,则是4个字节。这里的计算方式:1+4+(3)+4+(4)+8 = 24.

  • 64位和32位,数据类型大小的区别

最大的区别就是指针数据类型64位的大小是8个字节,32位的是4个字节

具体请参考:https://blog.youkuaiyun.com/puppet_master/article/details/50044965

  • 带有虚函数的单继承

子类继承一个带有虚函数的基类,无论子类有没有虚函数,或者有虚函数覆盖的情况,子类也只有一个虚函数表。

继承关系图如下:参考https://www.cnblogs.com/yanqi0124/p/3829964.html

基类和派生类之间的关系:其中基类的虚函数f在派生类中被覆盖了

 

class AA{
public:
    char i;
    int j;
    int k;
    virtual void func();
    virtual ~AA();
};

class BB : public AA{
public:
    int n;
    virtual void func();
};

 

输出:AA大小:24,BB大小:24

BB继承AA的所有数据,其数据成员存放顺序如下:

char i; 

int j;

int k;

int n;

计算方法:1+4+(3)+4+4+8(vptr大小) = 24

  • 多继承,基类如何有虚函数,则子类会保存一个指向基类虚表的指针。

继承关系图如下:参考https://www.cnblogs.com/yanqi0124/p/3829964.html

假设基类和派生类之间有如下关系:

对于子类实例中的虚函数表,是下面这个样子:

 

假设,基类和派生类又如下关系:派生类中覆盖了基类的虚函数f

下面是对于子类实例中的虚函数表的图:

从上图中可以看出,只要继承的父类有虚函数,那么子类就有一个对应的指向基类虚表的指针vptr。

class AA{
public:
    int i;
    virtual void funcd();
    virtual ~AA();
};

class BB{
public:
    int j;
    virtual void func();
    virtual ~BB();
};

class CC : public AA, public BB{
public:
    int k;
    virtual void func();
    ~CC();
};

输出:

AA大小:16

BB大小:16

CC大小:32

  • 虚继承,由于涉及到虚函数表和虚基表,会同时增加一个(多重虚继承下对应多个)vPtr指针指向虚函数表vbTable和一个vbPtr指针指向虚基表vbTable。

class AA{
public:
    int i;
    virtual void funcaa();
    virtual ~AA();
};

class BB : virtual public AA{
public:
    int j;
    virtual void funcbb();
    virtual ~BB();
};

class CC : virtual public AA{
public:
    int k;
    virtual void funccc();
    ~CC();
};

class DD : public BB, public CC{
    virtual void funcdd();
    ~DD();
};

 

输出:

AA大小:16

BB大小:32

CC大小:32

DD大小:48

虚继承根据编译器的不同,对象内存布局也不一样,再次强调,本文章里边所有测试环境是GCC编译器。GCC都是将虚表指针在整个继承关系中共享的,不共享的是指向虚基类的指针。

对于BB对象内存分析:

AA::vptr//虚表指针
AA::i 
BB::vbptr//虚基类指针
BB::vptr//虚表指针
BB::j 

由于虚函数指针共享,所以BB最终的大小计算:8(AA::vbptr)+(4+(4))(AA::i)+(4+(4))(BB::j)+8(vptr 共享虚函数指针)=32

CC跟BB是类似的计算。

DD的对象内存分析:

BB::vptr//虚表指针
BB::vbptr//虚基类指针
BB::j 
CC::vptr//虚表指针
CC::vbptr//虚基类指针
CC::k 
AA::vptr//虚表指针
AA::i 

 

DD大小计算:8(BB::vbptr)+(4+(4))(BB::j)+8(CC::vbptr)+(4+(4))(CC::k)+(4+(4))(AA::i)+8(vptr 共享虚函数指针)=48

补充:如果是在VC编译器上,则虚函数指针不共享。

 

 

 

【Bluetooth蓝牙开发】一、开篇词 | 打造全网最详细的Bluetooth开发教程 1、开篇词 2、蓝牙开发入门 3、蓝牙协议栈总览 4、蓝牙协议栈——物理层 5、蓝牙协议栈——链路层 6、蓝牙协议栈——传输层 7、蓝牙协议栈——L2CAP协议 8、蓝牙协议栈——ATT协议 9、蓝牙协议栈——GATT协议 10、蓝牙通信流程分析 11、蓝牙协议栈——Bluez交叉编译 12、蓝牙调试工具汇总 阅读详情

相关推荐

Vitis HLS 学习指南与实践教程

Vitis HLS 学习指南与实践教程摘要:本文系统介绍了AMD Vitis HLS工具及其应用。HLS技术将C/C++代码自动转换为硬件描述语言,显著提升FPGA开发效率(5-10倍)。文章对比了HLS与传统RTL设计的优势,包括抽象级别高、开发周期短、代码重用性强等特点。详细讲解了Vitis HLS工具链的核心功能,包括支持的C/C++特性(如任意精度数据类型)、开发流程(项目创建-代码编写-仿真-综合)以及关键优化技术(流水线、循环展开、数组分割等编译指示)。通过具体代码示例展示了HLS设计方法,为F

weixin_44707118的博客 1400

C++基本数据类型

C++基本数据类型 C++定义了一套包括算术类型和空类型在内的基本数据类型。其中算术类型包括字符、整型数、布尔值和浮点数;空类型不对应具体的值。算术类型的尺寸(数据所占的比特数)在不同的机器上有所差别,尺寸越大所能表示的数据范围就越大,但 C++标准规定了最小的尺寸值 一. 基本内置类型 1. 算数类型 算数类型分为两类:整形(包括字符类型、布尔类型)和浮点型 整型 短整型:short(最小尺寸:16位) 整型:int(最小尺寸:16位,至少和short一样长) 长整型:long (最小尺寸:

小Z今天学习了吗 1580

程序化广告行业(23/89):深度剖析广告效果评估指标

大家好,我一直希望能和大家一起在技术领域不断探索、共同进步。在之前的文章中,我们了解了程序化广告中腾讯的业务布局和广告效果评估的基础概念,今天让我们进一步深入剖析广告效果评估的各项指标,这对理解程序化广告的运作机制至关重要

yyy173611的博客 4863

C++的基本数据类型

C++的基本数据类型一共有12种分别是类型 类型 含义 最小尺寸(1字节=8位) bool 布尔类型 未定义 char 字符 8位 wchar_t 宽字符 16位 char16_t Unicode字符 16位 char32_t Unicode字符 32位 short 短整型 16位 int 整型 16位 long 长整型 32位 ...

weixin_45483906的博客 1204

(一)ANSYS WORKBENCH实践入门

ANSYS-workbench 有限元分析应用基础教程 (张晔)学习笔记

qq_51767372的博客 1万+

ArcGIS数据处理必备技能:从地理坐标到UTM投影的面转栅格完整流程

本文详细介绍了在ArcGIS中从地理坐标到UTM投影的面转栅格完整流程,包括坐标系转换、像元大小设置及质量控制等关键步骤。通过实战案例和Python脚本示例,帮助用户解决常见问题并优化数据处理效率,特别适合需要精确GIS数据分析的专业人士。

weixin_42628688的博客 180

C++中的基本数据类型

C++中的数据类型

吕爽 7862

【RL+空战】学习记录01:jsbsim 仿真环境初次学习,F16 战机起飞

【代码】【RL+空战】学习记录01:jsbsim 仿真环境初次学习,F16 战机起飞。

weixin_41369892的博客 901

C++ char 类型:字符型和最小的整型

C++ 中没有 byte,Java 中有 byte。但是 C++ 有 char,char 是可用来放整数的最小字节类型。#include <iostream> int main() { using namespace std; // 声明一个 char 类型的变量 char ch; cout << "Enter a charac...

weixin_30679823的博客 388

第四节、C# 上位机面向对象编程详解(工控硬件继承实战版)

继承核心价值:在 C# 上位机工控开发中,继承的核心是通用逻辑复用与接口统一,将所有硬件的通用属性 / 方法封装到抽象基类,子类只需实现独有逻辑,大幅减少冗余代码。基类设计要点:优先使用抽象基类,合理分配访问修饰符(privateprotectedpublic),定义通用事件与虚方法,提供资源释放机制,兼顾复用性与扩展性。子类设计要点:通过: base()调用基类构造函数,强制实现抽象方法(保证接口统一),选择性重写虚方法(实现独有逻辑),复用基类的protected成员。多设备管理。

kylezhao2019的博客 784

2015年高教社杯全国大学生数学建模竞赛 A 题:《太阳影子定位》真题解析与 MATLAB 解决方案

🏆 本文已收录于专栏:《滚雪球学数学建模(含历年真题)》,持续更新最新及历年数学建模竞赛资料,每篇内容力求做到“问题讲透、模型讲清、代码可用、论文可参考”,帮助你从零开始逐步建立完整的数学建模知识体系。

**My Coding Family** 1356

转:为什么C++中空类和空结构体大小为1?

参考:http://www.spongeliu.com/260.html 为什么C++中空类和空结构体大小为1? On November 17, 2010, inC语言,语言学习, by sponge 这篇文章是一篇译文,跟上一篇文章相呼应的,原文在这里。 对于结构体和空类大小是1这个问题,首先这是一个C++问题,在C语言下空结构体大小为0(当然这是编译...

weixin_33962923的博客 368

UG\NX二次开发 找不到指定的dlx文件(Specified Dlx file not found)

有群友问:用Ctrl+U运行的时候就报错,找不到指定的dlx文件Specified Dlx file not found。怎么处理。

王牌飞行员_里海的博客 1127

windows下和linux 高低字节,c++类的大小计算及分析windows中VS与Linux中gcc结果的差异...

c++类的大小计算及分析windows中VS与Linux中gcc结果的差异c++类的大小计算及分析windows中VS与Linux中gcc结果的差异写在开头:文中提到Windows中VS用的是默认的MSVC编译器,Linux使用Gcc编译器。其实在Windows下使用MinGW可以得到与Gcc一样的结果。另外,在结构体中存在long,int的时候还需要考虑编译器数据模型:关于int,long等数据...

weixin_30719609的博客 268

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

c++类的大小计算及分析windows中VS与Linux中gcc结果的差异

写在开头:文中提到Windows中VS用的是默认的MSVC编译器,Linux使用Gcc编译器。其实在Windows下使用MinGW可以得到与Gcc一样的结果。 另外,在结构体中存在long,int的时候还需要考虑编译器数据模型:关于int,long等数据类型占用字节数 喵哥最近在复习C++虚函数的时候遇到一道题,关于计算类的大小的问题,为了吃透这种题目,在网上找到几篇文章学习了一下。也...

喵哥的博客 831

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

【C++】类和对象(上):类的定义,类的实例化,类的大小,this指针,面试题分析

C++类对象——类的定义,访问限定符,类的实例化,类的大小,this指针,面试题分析

2502_94043640的博客 546

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

C++中类的内存空间大小(sizeof)分析

那么在C++中的类的内存空间大小又有哪些特殊的问题呢?     首先,我认为对齐肯定也是其中的问题之一,对齐主要是为了加快读取的速度。     关于对齐这个我认为基本上已经是操作系统内定好的,既然Linux与Windows存在差别,那么在C++的类中,关于对齐肯定也会存在一定的差别。关于对齐我认为只要记住平时使用的系统的对齐准则就可以了,即:在Windows中经常是以结构体重最大内置类

u013265795的专栏 2012

C++类(一)——前置声明

忙完毕业的事情了。更新继续! 前置声明 转自——C++类的前置声明- King先生 - 博客园 链接整理 1、出错代码 //错误代码。报错:error C2079: 'b' uses undefined class 'B' class B; class A{ public: B b; }; class B{ public:...

一直走,不要回头 1071

C++编程之旅-- -- --类与对象的奇幻征途之初识篇(一)(了解类的基本用法,计算类大小,分析this指针)

本文介绍了C++中类的基本概念和使用方法。主要内容包括: 面向对象与面向过程的区别:C++通过对象交互组织程序,隐藏实现细节 类的定义方式:使用class关键字,包含成员变量和成员函数 访问限定符的作用:public、protected、private实现封装 类的作用域和实例化:使用::操作符定义成员,类实例化后才分配内存 类对象大小计算:主要计算成员变量总大小,考虑内存对齐 this指针:编译器自动生成的隐含参数,指向当前对象 文章通过洗衣服等生活实例和代码示例,帮助理解面向对象编程思想,并详细说明了类

2403_87827685的博客 645

linux 中占12个字节,C++中类的内存空间大小(sizeof)分析

在C语言中存在关于结构体的存储空间大小是比较深入的话题,其中涉及计算机的基本原理、操作系统等。我认为对齐是C语言中让很多初学者都拿不准摸不透的问题,特别是在跨平台的情况下,对齐这种问题更加的复杂多变,每一种系统都有自己独特的对齐方式,在Windows中经常是以结构体重最大内置类型的存储单元的字节数作为对齐的基准,而在Linux中,所有的对齐都是以4个字节对齐。那么在C++中的类的内存空间大小又有哪...

weixin_39851872的博客 262

log4CPP多线程支持的缺角(一)(转)

[size=medium]log4CPP多线程支持的缺角(一)[/size]log4CPP是一款优秀的c++日志开源软件,虽然从很早的时代就宣称了对于多线程的支持,而且源码中有很好的利用栈对象封装互斥锁,一种很好的使用资源实践;而且下载下来用vc6编译,也能检查到其连接的c语言库函数设定的为multiThread DLL,所以,从骨架上支持多线程应该没有多少疑问。 但是对于Rolli...

jcair的博客 614

C++类大小确定,构造、析构、静态、动态绑定(分析一道Oracle面试题)

 题目给出一段C++代码,要求写出运行结果,代码如下,大家可以自己先试一下:#include using namespace std; class A{ public: A(){ cout

jim_wei的专栏 1633

7、类的大小

在GCC x86 64Bit中,一个empty virtual base class被视作derived class object最开头的一部分,也就是说它没有花费任何的额外空间。上述的X,Y,Z,A中没有任何一个class内含有明显的数据,其间只表示了继承关系,所以有人认为每个class的大小应该是0。在32位计算机中,通常alignment为4bytes(32位),以使bus的“运输量”达到最高的效率。对于C++的类而言,类的大小似乎并非完全由用户控制,我们看看如下的代码。

u012750235的博客 461

C/C++中结构体和类大小

类大小及结构体大小的解析

向往天空的鱼 1764
上一篇: Vector 容器快速删除方法
下一篇: 并发编程三大特性
OODeveloper
博客等级 码龄12年 43粉丝 137原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值