C++_类和结构体所占内存大小,静态成员问题

静态成员未初始化或者未调用(当然静态成员必须类外初始化才能调用)是不占内存的。静态成员不占类或结构体的内存
静态成员函数同样只声明未定义同样不占内存

指针在64位机8个字节,32位机4个字节,
可以参考指针大小与32位、64位系统

// vector::emplace_back
#include <iostream>
#include <vector>
struct dddd{int x;int y;static int z;dddd(int a,int b):x(a),y(b){}void dd(){}static int cc();
};
int dddd::cc(){}
int dddd::z=0;
int main ()
{/*std::vector<dddd> myvector;myvector.emplace_back (100,200);std::cout << "myvector contains:";/*for (auto& x: myvector)std::cout << ' ' << x.second;std::cout << '\n';*/dddd::z=0;std::cout<<sizeof(dddd)<<std::endl;return 0;
}

1.结构体所占大小计算

结构体存在内存对齐,类(对象)也如此,甚至于所有变量在内存中的存储也有对齐一说(只是这些对程序员是透明的,不需要关心)。实际上,这种对齐是为了在空间与复杂度上达到平衡的一种技术手段,简单的讲,是为了在可接受的空间浪费的前提下,尽可能的提高对相同运算过程的最少(快)处理。

先看以下程序

#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;
}

对齐规则是按照成员的声明顺序,依次安排内存,对齐字节数为最大成员变量的字节大小,偏移量为最大成员变量的字节数的整数倍,在这个程序中对齐字节数为4

#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;
}

aa是最大字节8个,所以temp2开始补齐,所以总的为24

#include<stdio.h>
union ss
{int a;double b;
};
struct MyStruct
{int temp1;//4个字节char  temp2;//1个字节char temp3;//1个字节,对齐是8个字节,还需2个字节补齐ss aa;//8个字节short temp4;short temp5;short temp6;short temp7;short temp8;//2个字节,补齐还需要6个字节
};
int main()
{printf("%d", sizeof(MyStruct));return 0;
}

大小为32

#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>
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

空结构体大小为1

c++要求每个实例在内存中都有独一无二的地址。空类也会被实例化,所以编译器会给空类隐含的添加一个字节,这样空类实例化之后就有了独一无二的地址了。所以空类的sizeof为1。结构体在是特殊的类

2.类内存大小计算

类只用计算成员变量与指针的大小,空类也会被实例化,所以编译器会给空类隐含的添加一个字节,这样空类实例化之后就有了独一无二的地址了。所以空类的sizeof为1。静态成员变量和静态成员函数都是类的所有对象共享的,静态成员变量存放在全局存储区,静态成员变量和静态成员函数在编译时就已经在全局区分配的内存。

#include<iostream>
using namespace std;
class student
{static int b;static void func();
};
int main()
{cout << sizeof(student) << endl;return 0;
}

大小为1

class CBase
{
public:
CBase(void);
virtual ~CBase(void); //1个字节
private:
int  a;
char *p; //1个字节补齐3个字节
};

大小为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;
}

大小为12派生类会继承父类的成员变量和虚函数等,所以子类的内存大小是在父类的内存大小的基础上加上自己增加的内存大小。G++实测24个字节,我的理解是虚函数指针8个字节(实测只有虚函数的情况下),int,char补齐8个字节,继承按道理讲是直接16+4=20个字节,我的理解是补齐4个字节,所以24个字节,实测也是这样的

#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 c;//4个字节
};
int main()
{cout << sizeof(student1) << endl;return 0;
}

24个字节

#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 c;//4个字节int a;//4个字节,补齐4个
};
int main()
{cout << sizeof(student1) << endl;return 0;
}

32个字节

#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个,g++64位机实测24

测试如下代码:发现原因,虚函数指针在64位机8个字节,在32位机是4个字节,不论有几个虚函数但只有一个虚函数指针,所以即使存在3个虚函数大小还是8或4;

#include<iostream>
using namespace std;
class student
{int a;char c;static int b;
public:static void func();virtual void CC(){};
};
class student1
{//int d;
public:void CC(){std::cout<<"1";};virtual void eat(){};virtual void at(){};virtual void t(){};
};
int main()
{student * aa;student1 bb;//aa=&bb;//aa->CC();std::cout<<sizeof(student1)<<endl;return 0;
}

64位机G++测试结果为8

#include<iostream>
using namespace std;
class student
{int a;char c;static int b;
public:static void func();virtual void CC(){};
};
class student1:public student
{//int d;
public:void CC(){std::cout<<"1";};virtual void eat(){};virtual void at(){};virtual void t(){};
};
int main()
{student * aa;student1 bb;//aa=&bb;//aa->CC();std::cout<<sizeof(student1)<<endl;return 0;
}

G++64位机测试为16,int d加上 测试为24

可以看出按照虚指针的大小进行补齐;

问题:子类声明了一个虚函数且该虚函数是父类中没有的虚函数为什么子类没有新产生一个虚函数指针。

这个涉及到内存布局问题,首先是基类产生了一个虚函数指针,这个虚函数指针会指向虚函数表,表中存放的是基类的虚函数。子类也会继承到这个虚函数指针,虚函数指针指向虚函数表,表中先是存放基类的虚函数,再存放子类的基函数,如果子类重载了父类的某些虚函数,那么新的虚函数将虚函数表中父类对应的虚函数覆盖

虚继承——空类

#include<iostream>
using namespace std;
class student
{};
class student1: virtual student
{};
int main()
{cout << sizeof(student1) << endl;return 0;
}

g++测试为64位机8个字节,如上虚指针的红字部分

#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;
}

G++测试为32;按8位补齐因为虚继承会再产生一个虚函数指针,去指向对应的基类,防止子类继承多个一样的基类,造成资源浪费

#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;
}

64位机G++测试为32;按8位补齐。此时是子类声明的虚函数是父类没有的,则此时子类会再产生一个虚函数指针,如果此时子类的所有虚函数都是继承自基类的,则不会产生虚函数指针。

参考:struct和class内存大小的计算

C++中 类 和 结构体所占内存大小

C++_类和结构体所占内存大小,静态成员问题相关推荐

  1. 共用体和结构体所占内存大小的计算方法

    共同体作用:让几个不同类型的变量共享同一个内存地址. 共用体所占内存大小:共用体所占内存的大小即公用体中长度最大元素所占用的字节数. #include<stdio.h> typedef u ...

  2. C语言计算出结构体所占空间大小

    第一次写博客,而且是一个小萌新,有什么错误的地方请各位大佬及时提出来,我会立即更改,最后希望这篇文章能对你有帮助 大家对用struct关键字创建一个结构体应该不陌生,但是我们创建的结构体的空间大小怎么 ...

  3. 结构体所占内存的字节数——内存对齐

    1.什么是内存对齐? 下面先来看一个例子: #include <stdio.h> int main() {struct Text1{char c1;short s; char c2;int ...

  4. 如何计算结构体所占字节大小

    结构体的大小并不是简单的内部结构加加加,而是有特殊的对齐规则. 一.对齐数 struct name { int a;//一个成员 char b; double c; }; 在此之前需要引入一个对齐数的 ...

  5. Swift —— 类与结构体

    Swift -- 类与结构体 1. 初识类与结构体 1.1 异同点 1.2 类(引用类型) 1.3 结构体 (值类型) 1.4 类和结构体的内存位置 1.4.1 结构体的内存位置 1.4.2 类的内存 ...

  6. 内存对齐 | 原来字段顺序还能影响结构体占用的内存空间

    大家好啊,不知道看了网管在上周的文章Go指针的使用限制和unsafe.Pointer突破之路,你们有没有感觉Golang 比之前想的还好用呢?确实能直接读写内存,很多以前觉得无能为力的事情就不再是问题 ...

  7. C/C++计算类/结构体和联合体(union)所占内存大小(内存对齐问题)

    目录 一,内存对齐的三条规则 二,注意事项: 三,举例说明 1,示例1 2,示例2 3,示例3 4,示例4 四,联合体(union) 五,字节对齐的原因 六,计算练习 一,内存对齐的三条规则 数据成员 ...

  8. ios 结构体跟枚举变量的区别_[Swift]枚举、类与结构体的对比

    ###枚举.类与结构体的对比### ####枚举与其他两者的关系#### 首先说枚举,相对比较好区分,因为我们知道,枚举与其他两者最大的相同之处就在于都可以定义方法. 而其他的更多特性,对于枚举基本没 ...

  9. Swift中的类和结构体(2)

    Swift中的类和结构体(2) 异变方法 方法调度 影响函数派发方式 异变方法 在Swift中,值类型属性不能被自身的实例方法修改,编译器不会通过编译,报错Left side of mutating ...

最新文章

  1. Log4j格式化符号
  2. 利用NPP-VIIRS夜光数据识别中国收缩城市
  3. Django 2.2 LTS 发布,长期支持版来了
  4. 为什么我的索尼电视显示服务器异常,索尼液晶电视有哪些故障 索尼电视故障代码大全【详解】...
  5. jQuery07源码 (3803 , 4299) attr() prop() val() addClass()等 : 对元素属性的操作
  6. 计算机翻译字串符,字符的计算机处理和显示 外文翻译.doc
  7. SQL Server触发器创建、删除、修改、查看示例步骤
  8. 统计学习方法读书笔记3-感知机SVM
  9. SQL-实现excel向下填充的功能
  10. 苹果用计算机加个微信怎么弄的,教你苹果怎么用双开微信,就是这么简单!
  11. google guava Joiner 示列
  12. java网络爬虫如何控制爬取的深度_Java 动手写爬虫: 二、 深度爬取
  13. 如果令 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 分别等于
  14. 任志强2018首谈房价:买房去北京新机场 千万别去崇礼
  15. 敲笨钟 (20 分)
  16. 傅里叶变换复数形式的实部代表什么_「趣味数学」傅里叶变换及其在人工智能中的应用...
  17. 系统穿越频率用matlab,基于Matlab的自动控制系统设计
  18. I2C协议介绍以及HAL库实现I2C对SHT30温湿度采样
  19. Nutanix与联想深化合作伙伴关系,以超融合全面赋能新基建
  20. 魔兽争霸war3心得体会(四):不死族vs人族1本火魔塔

热门文章

  1. 在 VS Code 里逛知乎、发文章?Zhihu on VSCode 来啦!重新定义内容创作!
  2. 叶际微生物定殖模型研究进展
  3. 一作解读Microbiome:所谓的“富集培养”获得的微生物真的都是被“富集”出来的吗?
  4. R语言应用str_match函数和str_match_all函数从字符串抽取匹配的字符串模式:str_match函数抽取第一个匹配的字符串模式、str_match_all函数抽取多个匹配的字符串模式
  5. pandas使用date_range函数按照指定的频率(freq)和指定的个数(periods)生成dataframe的时间格式数据列
  6. R语言使用ggpubr包的ggarrange函数组合多张结论图:使用ggpubr包在散点图的侧面添加辅助图形、并使用NULL将不需要可视化的侧面留白
  7. 什么是维度诅咒?如何评估降维算法在当前任务数据集上的效果?
  8. 数据不平衡(class_weight、评估方法、上采样、下采样)、详解及实战
  9. java jaxb 集合_java.util.List是一个接口,JAXB不能处理接口
  10. 过程中存根的作用有_模温机的作用 模压过程中模温机的作用有哪些?