• C++对象内存故事, 一个对象是如何由子对象来构成的?


    关于对象的数据成员,请读者记住下述两个结论:

    • 每个对象拥有独立的存储空间,存储自己的数据成员。
    • 相同类型的对象所拥有的数据成员,其类型、数量和名称相同。例如,dora和peter都是Person类型的对象,所以他们都有姓名、身份证号、性别、体重等属性。

    本文引用自作者编写的下述图书; 本文允许以个人学习、教学等目的引用、讲授或转载,但需要注明原作者"海洋饼干叔
    叔";本文不允许以纸质及电子出版为目的进行抄摘或改编。
    1.《Python编程基础及应用》,陈波,刘慧君,高等教育出版社。免费授课视频 Python编程基础及应用
    2.《Python编程基础及应用实验教程》, 陈波,熊心志,张全和,刘慧君,赵恒军,高等教育出版社Python编程基础及应用实验教程
    3. 《简明C及C++语言教程》,陈波,待出版书稿。免费授课视频

    下述C++程序通过对一个Person对象的解析,来说明一个Person类型的对象是如何由其他子对象来构成,以及这些子对象是如何存储在一个Person对象的内部的。

    1   //Project - PersonMemory
    2   #include <iostream>
    3   #include <stdio.h>
    4   using namespace std;
    5   ...                     //...表示代码有省略
    6   class Person{
    7   public:
    8       string sName;       //姓名
    9       string sID;         //身份证号
    10       GenderType gender;  //性别
    11       int iWeight;        //体重,以克为单位
    12    ...
    13   };  //注意末尾的分号不能少
    14   
    15   int main(){
    16       printf("sizeof(Person) = sizeof(string) x 2 + sizeof(GenderType) "
    17              "+ sizeof(int)\n= %lld x 2 + %lld + %lld \n= %lld\n",
    18              sizeof(string),sizeof(GenderType),sizeof(int),sizeof(Person));
    19   
    20       Person a("3604020001", "Peter Lee");
    21   
    22       printf("&a         = %p, sizeof(a)        = %lld\n",
    23              &a, sizeof(a));
    24       printf("&a.sName   = %p, sizeof(a.sName)  = %lld\n",
    25              &a.sName, sizeof(a.sName));
    26       printf("&a.sID     = %p, sizeof(a.sID)    = %lld\n",
    27              &a.sID, sizeof(a.sID));
    28       printf("&a.gender  = %p, sizeof(a.gender) = %lld\n",
    29              &a.gender, sizeof(a.gender));
    30       printf("&a.iWeight = %p, sizeof(iWeight)  = %lld\n",
    31              &a.iWeight, sizeof(a.iWeight));
    32   
    33       return 0;
    34   }
    

    上述程序的执行结果为:

    1   sizeof(Person) = sizeof(string) x 2 + sizeof(GenderType) + sizeof(int)
    2   = 32 x 2 + 4 + 4
    3   = 72
    4   Person::Person(), sName = Peter Lee
    5   &a         = 000000000062fd60, sizeof(a)        = 72
    6   &a.sName   = 000000000062fd60, sizeof(a.sName)  = 32
    7   &a.sID     = 000000000062fd80, sizeof(a.sID)    = 32
    8   &a.gender  = 000000000062fda0, sizeof(a.gender) = 4
    9   &a.iWeight = 000000000062fda4, sizeof(iWeight)  = 4
    

    说明:在读者的计算机上,执行结果中的地址很可能与本书不同。此外,不同的编译器下,string类型的大小,GenderType类型的大小也可能与本书不同。

    🚩第6 ~ 13行:一个Person类型的对象,依次包含sName、sID、gender及iWeight共4个数据成员,其类型分别为string、string、GenderType和int。

    🚩第16 ~ 18行:打印Person、string、GenderType及int类型的字节数。执行结果的第1 ~ 3行证实,一个Person对象的大小正好等于两个string对象、1个GenderType对象及1个int对象的大小之和。即对象的尺寸等于构成该对象的全部子对象尺寸之和

    🚩第20行:定义Person类型的对象a,构造函数Person::Person()被执行,对a进行了初始化。

    🚩第22 ~ 31行:打印了a的全部数据成员的地址及大小。根据输出结果,我们绘制了对象a的内存结构,见图13-2。
    图13-2 对象a的内存结构
    如图13-2所示,Person类型的对象a占据了从0x0062fd60开始的连续72个字节的空间。由于a属于自动变量,因此,其内存空间位于栈内。a的4个数据成员按定义顺序依次排列在这72个字节的空间内,其中,sName和sID各占32个字节,gender占4个字节,iWeight占4个字节。

    如第5章所述,string类型的对象尺寸是固定的(如本例中的32个字节),但却可以存储几乎长度不限的字符串。其秘密在于:

    • string对象内部并不存储实际的字符数组,对象内部所存储的只是用于管理实际字符数组的数据结构,例如指向实际字符数组的指针;
    • string对象将实际的字符数组安排在**堆(heap)**里,并使用对象内部的指针指向申请的动态内存。此外,string对象还会根据实际存储的字符串的长度来动态调整所占用的堆空间,以避免浪费。

    从图13-2可见,a.sName,a.sID的实际字符串事实上并不在对象内部,而是在堆里。在作者的计算机上,sizeof(Person)以及sizeof(a)均为固定的72个字节,不论a.sName以及a.sID所包含的字符串实际有多长。也就是说,使用sizeof操作符获得的对象尺寸不包含对象动态创建的部分。

    为了帮助更多的年轻朋友们学好编程,作者在B站上开了两门免费的网课,一门零基础讲Python,一门零基础C和C++一起学,拿走不谢!

    简洁的C及C++
    由编程界擅长教书,教书界特能编程的海洋饼干叔叔打造
    Python编程基础及应用
    由编程界擅长教书,教书界特能编程的海洋饼干叔叔打造

    如果你觉得纸质书看起来更顺手,目前Python有两本,C和C++在出版过程中。

    Python编程基础及应用

    Python编程基础及应用实验教程
    在这里插入图片描述

  • 相关阅读:
    初步认识泛型
    每日4道算法题——第001天
    【Linux】对进程PCB的理解&&查看进程信息的方法
    机器学习02
    C++ Builder XE关于AdvStringGrid对EXCEL母表快速分表,并批量插入sheet子表简单操作
    CRM系统中人工智能对销售业务的帮助
    【ClickHouse】SQL 操作(Update 和 Delete、查询操作、alter 操作、导出数据) (四)
    计算机网络常考协议(HTTP&HTTPs、TCP/UDP、DNS)
    淘宝/天猫获取卖出的商品订单列表 API
    神经网络预测结果都一样,神经网络预测结果分析
  • 原文地址:https://blog.csdn.net/SeaBiscuitUncle/article/details/127047074