说了这么久的 C++ 终于说到类了,还是从内存出发来讨论一下 C++ 的类在内存中的存储方式(之前写过一篇内存对齐的文章,类同样在一定程度上遵循内存对齐原则,不过比结构体复杂一下)

如有侵权,请联系删除,如有错误,欢迎大家指正,谢谢

0.空类

class Test {};Test t0;
cout << sizeof(t0) << endl;
// 运行结果:1

解释:

  • 空类,没有任何成员变量和成员函数,编译器是支持空类实例化对象的,对象必须要被分配内存空间才有意义,这里编译器默认分配了 1Byte 内存空间(不同的编译器可能不同)

1. 含有成员变量的类

// ====== 测试一 ======
class Test {private:int i;char c;double d;
};Test t11;
cout << sizeof(t11) << endl;
// 运行结果:16// ====== 测试二 ======
class A{};class Test {private:int i;char c;double d;A a;
};Test t12;
cout << sizeof(t12) << endl;
// 运行结果:24// ====== 测试三 ======
class A {private:double dd;int ii;int* pp;
};class Test {private:int i;A a;double d;char* p;
};Test t13;
cout << sizeof(t13) << endl;
// x86目标平台运行结果:40;x64目标平台下运行结果:48

解释:

  • 这里的类的内存对齐原则与前面写的结构体的内存对齐原则是一样的(不太了解的可以移步我之前的《C/C++中内存对齐问题的一些理解》查看)
  • 测试三中,32bit 目标平台寻址空间是 4Byte(32bit),所以指针是 4Byte的;64bit 目标平台寻址空间是 8Byte(64bit),所以指针是 8Byte
  • 另外,静态成员变量是在编译阶段就在静态区分配好内存的,所以静态成员变量的内存大小不计入类空间(不太了解C++内存分布的可以移步我之前写的《C/C++程序的内存分布》查看)

2.含有成员变量和成员函数的类

// ====== 测试一 ======
class Test {private:int n;char c;short s;
};Test t21;
cout << sizeof(t21) << endl;
// 运行结果:8// ====== 测试二 ======
class Test {public:Test() {}int func0() {return n;}friend int func1();int func2() const {return s;}inline void func3() {cout << "inline function" << endl;}static void func4() {cout << "static function" << endl;}~Test() {}private:int n;char c;short s;
};int func1() {Test t;return t.c;
}Test t22;
cout << sizeof(t22) << endl;
// 运行结果:8// ====== 测试三 ======
class Test {public:Test() {}int func0() {return n;}friend int func1();int func2() const {return s;}inline void func3() {cout << "inline function" << endl;}static void func4() {cout << "static function" << endl;}virtual void func5() {cout << "virtual function" << endl;}~Test() {}private:int n;char c;short s;
};int func1() {Test t;return t.c;
}Test t23;
cout << sizeof(t23) << endl;
// x86目标平台运行结果:12;x64目标平台下运行结果:16

解释:

  • 因 C++中成员函数和非成员函数都是存放在代码区的,故类中一般成员函数、友元函数,内联函数还是静态成员函数都不计入类的内存空间,测试一和测试二对比可证明这一点
  • 测试三中,因出现了虚函数,故类要维护一个指向虚函数表的指针,分别在 x86目标平台和x64目标平台下编译运行的结果可证明这一点

总结

  • C++编译系统中,数据和函数是分开存放的(函数放在代码区;数据主要放在栈区和堆区,静态/全局区以及文字常量区也有),实例化不同对象时,只给数据分配空间,各个对象调用函数时都都跳转到(内联函数例外)找到函数在代码区的入口执行,可以节省拷贝多份代码的空间
  • 类的静态成员变量编译时被分配到静态/全局区,因此静态成员变量是属于类的,所有对象共用一份,不计入类的内存空间
  • 静态成员函数和非静态成员函数都是存放在代码区的,是属于类的,类可以直接调用静态成员函数,不可以直接调用非静态成员函数,两者主要的区别是有无this指针,更加详细的解释后面专门写一篇文章
  • 内联函数(声明和定义都要加inline)也是存放在代码区,内联函数在被调用时,编译器会用内联函数的代码替换掉函数,避免了函数跳转和保护现场的开销(实际上到底替不替换还要由编译器决定,即使声明为内联函数也有可能不替换,未声明成内联函数也有可能被编译器替换到调用位置,主要由编译器决定),更详细的介绍后面也会专门写一篇文章

参考文章:

[1] C++成员函数在内存中的存储方式

[2] C++类的实例化对象的大小之sizeof() (该文章有一处错误,“如果是指针,则无论指针指向的是什么数据类型,都占4个字节的存储空间”,在x86目标平台下4Byte,在x64目标平台下8Byte)

如果未特殊说明,以上测试均是在win10 vs2017 64bit编译器下进行的

c++全局类对象_C++ 类在内存中的存储方式(一)相关推荐

  1. JavaScript中数据在内存中的存储方式

    JavaScript中数据在内存中的存储方式 1.js数据类型分类 简单数据类型:Number.String.Boolean.Undefined.Null 复杂数据类型:Object.Array.Fu ...

  2. c语言double数据存储形式,C语言 float、double数据在内存中的存储方式

    float在内存中占4个字节(32bit),32bit=符号位(1bit)+指数位(8bit)+底数位(23bit) 指数部分 指数位占8bit,可以表示数值的范围是0-(表示0~255一共256个数 ...

  3. C语言的数据类型大全,整型数据在内存中的存储方式

    一.数据类型 通过长时间的学习C语言以及代码的编写,我掌握了很多很多的数据类型,下面就给大家罗列一下. 1.内置数据类型 char        //字符数据类型--                  ...

  4. 【C语言】浮点型数据在内存中的存储方式

    目录 一. 前言 二. 问题的引出 三. 两类浮点型数据(float.double)在内存中的存储方式 3.1 两类浮点型数据的存储模型 3.1.1 浮点型数据数值读取的通用模型 3.1.2 floa ...

  5. C/C++浮点数在内存中的存储方式《转》

    那天有人在汇编群里有人问了一个 #include <iostream> #include <stdio.h> using namespace std; int main() { ...

  6. IEEE754标准: 浮点数在内存中的存储方式

    一. 什么是IEEE754标准 我们知道, 计算机内部实际上只能存储或识别二进制. 在计算机中, 我们日常所使用的文档, 图片, 数字等, 在储存时, 实际上都要以二进制的形式存放在内存或硬盘中, 内 ...

  7. C语言程序设计 | 整型、浮点型在内存中的存储方式

    整型在内存中的存储 一个变量的创建要在内存中开辟空间,空间的大小是根据不同的类型决定的. 那数据在数据在所开辟的空间中是如何存储的呢? 首先我们要了解三个概念: 原码 反码 补码 计算机中的有符号数有 ...

  8. C语言浮点数据在内存中的存储方式

    float在内存中的存储遵循IEEE 754标准.在C/C++中,float类型占4个字节即32位 , 这32位分成了3部分: 符号位最为简单,如果你存储的是正数那么符号数就是0.如果是负数,则为1. ...

  9. 十进制浮点型数据转换成二进制,并在内存中的存储方式

    文章源地址:http://blog.csdn.net/wzy198852/article/details/9617239   原文章有些地方有误,已更正 十进制小数的二进制表示: 整数部分:除以2,取 ...

最新文章

  1. java+js上传图片_java+ jsp+js 实现富文本编辑和上传图片功能
  2. 腾讯精选练习 50 题(Leetcode)笔记 PDF下载!
  3. 《深度探索C++对象模型》--7 站在对象模型的尖端
  4. 18 个 Python 高效编程技巧,Mark!
  5. JUC队列-ArrayBlockingQueue(一)
  6. Cloud for Customer ApplicationStarter.js和fQuickLogin
  7. YYSSW的完整格式是什么?
  8. 线性回归—梯度下降python实现
  9. python socket thread,python实现socket+threading处理多连接的方法
  10. Centos7 防火墙 ( firewalld ) 和 Selinux 一些简单操作命令
  11. java类型的转换顺序_Java数据类型自动转换的优先顺序
  12. C语言——指针详解(必收藏)
  13. 数学建模——相关系数、皮尔逊相关系数、斯皮尔曼相关系数
  14. Linux系统下QT九宫格拼图小游戏
  15. 决定了,儿童节我们用python画这个...
  16. 1000亿资本“壕掷”!乡村旅游迎来黄金时代?
  17. 毕业设计--20200228--内网搭建domoticz系统 frp内网穿透实现天猫精灵控制内网设备
  18. 膜拜!用最少的代码却实现了最牛逼的滚动动画
  19. java毕业设计社区管理系统Mybatis+系统+数据库+调试部署
  20. 都会演出连城诀—诺基亚N78决战入手入手了!

热门文章

  1. Android官方开发文档Training系列课程中文版:后台服务之IntentService的使用
  2. 领域情报搜索实践:真实场景下的问答实施策略与风险分析
  3. 2017-2018-1 20155338 《信息安全系统设计基础》第七周学习总结
  4. VS2017C++单元测试
  5. Network Request Failed
  6. 对接第三方支付接口-类似文件锁的编程小技巧
  7. 个人觉得好的文章链接推荐【转载,侵权立删】
  8. Hadoop分布式集群安装配置
  9. 分区助手扩大c盘后自动修复_磁盘分区工具,这个好用;无论调整C盘还是系统迁移...
  10. windows css,CSS (Windows) | Microsoft Docs