zoukankan      html  css  js  c++  java
  • C/C++ sizeof函数解析——【结构体】【类】

     转载自:https://www.cnblogs.com/0201zcr/p/4789332.html

    C/C++中不同数据类型所占用的内存大小

                         32位                 64位 

    char               1                    1 

    int                  4             大多数4,少数8 

    short              2                    2

    long               4                    8 

    float               4                    4 

    double            8                    8 

    指针                    4                         8

    (单位都为字节)

    结构体(struct):比较复杂,对齐问题。

    联合(union):所有成员中最长的。

    枚举(enum):根据数据类型。

     

    结构体sizeof

      先介绍一个相关的概念——偏移量。偏移量指的是结构体变量中成员的地址和结构体变量地址的差。结构体大小等于最后一个成员的偏移量加上最后一个成员的大小。显然,结构体变量中第一个成员的地址就是结构体变量的首地址。因此,第一个成员i的偏移量为0。第二个成员c的偏移量是第一个成员的偏移量加上第一个成员的大小(0+4),其值为4;第三个成员j的偏移量是第二个成员的偏移量加上第二个成员的大小(4+1),其值为5。

          然而,在实际中,存储变量时地址要求对齐,编译器在编译程序时会遵循两条原则

          (1)结构体变量中成员的偏移量必须是成员大小的整数倍(0被认为是任何数的整数倍) 

          (2)结构体大小必须是所有成员大小的整数倍,也即所有成员大小的公倍数。

    sizeof计算嵌套的结构体大小

         对于嵌套的结构体需要将其展开。对结构体求sizeof时,上述两种原则变为:

           (1)展开后的结构体的第一个成员的偏移量应当是被展开的结构体中最大的成员的整数倍。

           (2)结构体大小必须是所有成员大小的整数倍,这里所有成员计算的是展开后的成员,而不是将嵌套的结构体当做一个整体。

    类的sizeof

    1空类

    class A {};
    1
    大小为1。
    类的实例化就是给每一个实例在内存中分配一块地址。空类被实例化时,会由编译器隐含的添加一个字节。所以空类的size为1。
    2 虚函数


    当C++类中有虚函数的时候,会有一个指向虚函数表(V-table)的指针,所有的虚函数都在这个表中。指针大小为4,所以size为4。

    为了效率问题,编译器(gcc 和 微软)一般会把虚指针放在类的内存空间的最前面的位置,不管虚函数声明的位置。考虑对齐,大小都是 4 +1+1+2 = 8.

    3 静态数据成员


    静态数据成员被编译器放在程序的一个global data members中,它是类的一个数据成员,但不影响类的大小。不管这个类产生了多少个实例,还是派生了多少新的类,静态数据成员只有一个实例。静态数据成员,一旦被声明,就已经存在。 考虑到数据对齐, 最终是8字节。

    4 普通成员函数

    class A
    {
    public:
    void fun() {};
    };

    大小为1。
    类的大小与构造函数,析构函数,普通成员函数无关。

    5 普通单继承


    大小分别为4 和 8。 可以看到普通的继承就是基类的大小+派生类自身的大小。注意数据对齐。
    注意:类的数据成员按其声明顺序加入内存,无访问权限无关,只看声明顺序。

    6 含虚函数的单继承

    7 虚单继承

    8 普通多继承

    9 虚函数多继承

     1 class A
     2 {
     3     virtual void fun() {}
     4 };
     5 
     6 class B
     7 {
     8     virtual void fun2() {}
     9 };
    10 class C : public  A, public B
    11 {
    12 public:
    13     virtual void fun3() {}
    14 };

    4 4 8

    类A一个虚函数表,类B一个虚函数表,类C继承了两个虚函数表,并把自己的虚函数写在了继承顺序中第一个虚函数表中。

    10 虚继承

    作者:zhengjihao
    来源:CSDN
    原文:https://blog.csdn.net/zhengjihao/article/details/77825269
    版权声明:本文为博主原创文章,转载请附上博文链接!

  • 相关阅读:
    jQuery瀑布流实例无限滚动加载图片
    【转载】IEnumerable<T>和IQueryable<T>区分
    【转载】C#数组,List,Dictionary的相互转换
    【转载】IQueryable和IEnumerable
    【转载】ABP源码分析一:整体项目结构及目录
    【转载】.NET深入解析LINQ框架(四:IQueryable、IQueryProvider接口详解)
    C# DataTable 转换 Model实体类,DataTable 转换 List 集合
    【转载】N 种仅仅使用 HTML/CSS 实现各类进度条的方式
    【转载】IQueryable 和 IEnumerable 的区别
    【转载】SQL Server Profiler工具
  • 原文地址:https://www.cnblogs.com/lijiaxin/p/10661018.html
Copyright © 2011-2022 走看看