zoukankan      html  css  js  c++  java
  • C++类的大小

    转载自https://blog.csdn.net/zhengjihao/article/details/77825269
    虚继承相关的内容可以参考https://www.cnblogs.com/BeyondAnyTime/archive/2012/06/05/2537451.html

    1.空类

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

    2.虚函数

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

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

    在来看如下代码:

    class A
    {
    public:
        char b;
        short c;
        int a;
    };
    class B
    {
    public:
        char a;
        int c;
        short b;
    };
    

    考虑数据对齐,大小分别为 8 和 12。如果我们将int 换成虚函数,回事什么结果呢?

    class A
    {
    public:
        char b;
        short c;
        virtual void fun() {}
    };
    class B
    {
    public:
        char a;
        virtual void fun() {}
        short b;
    };
    

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

    3.静态数据成员

    class A
    {
    public:
        char b;
        virtual void fun() {};
        static int c;
    };
    

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

    4.普通成员函数

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

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

    5.普通单继承

    class A 
    {
        int c;
    };
    class B : public A
    {
        int a;
    };
    

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

    class A
    {
        int a;
        char b;
    };
    class C : public A
    {
    public:
        char c;
    };
    

    上面这段代码,不同的编译器结果不同,VS的结果是 8 和 12, GCC是8 和 8。
    VS中 相当于

    class C
    {
        A a;
        char c;
    };
    

    A的大小为8,对齐值为4, 则考虑总体对齐 8 + 1 + 3(padding) = 12。
    GCC 则是

    class C
    {
        int a;
        char b;
        char c;
    };
    

    结果为 4 + 1 + 1 + 2 = 8。

    6.含虚函数的单继承

    class A
    {
        virtual void fun () {}
    };
    class C : public A
    {
    public:
        virtual void fun2() {}
    };
    

    大小分别为4 和 4。派生类继承了基类的虚指针,所以大小为4。

    7.虚单继承

    class A
    {
        virtual void fun () {}
    };
    
    class C : virtual public  A
    {
    public:
        virtual void fun2() {}
    };
    

    这段代码,VS和gcc结果不一样。VS为 4 和 12。 gcc为4 和4。

    8.普通多继承

    class A
    {
        int a;
        char b;
    };
    
    class B
    {
        char b;
    };
    class C : public  A, public B
    {
    public:
        char c;
    };
    

    VS:8 1 12
    GCC:8 1 8
    VS中相当于把A B当做整体看待, GCC则拆分整合。

    9.虚函数多继承

    class A
    {
        virtual void fun() {}
    };
    
    class B
    {
        virtual void fun2() {}
    };
    class C : public  A, public B
    {
    public:
        virtual void fun3() {}
    };
    

    结果为 4 4 8。分析:类A一个虚函数表,类B一个虚函数表,类C继承了两个虚函数表,并把自己的虚函数写在了继承顺序中第一个虚函数表中。

    10.虚继承

    class A
    {
        virtual void fun() {}
    };
    
    class B
    {
        virtual void fun2() {}
    };
    class C : virtual public  A, virtual public B
    {
    public:
        virtual void fun3() {}
    };
    

    GCC: 4 4 8
    VS:4 4 16

  • 相关阅读:
    oracle expdp和impdp常用命令选项
    oracle expdp导出远程数据到本地
    oracle目录操作
    反射
    设置查询对话框的F7
    Uncaught TypeError: timeout.close is not a function. when try to use clearInterval
    timestamp to time 时间戳转日期
    react+antd 选项卡切换
    react antd Warning: must set key for <rc-animate> children
    微信企业号报Error: echostr校验失败,请您检查是否正确解密并输出明文
  • 原文地址:https://www.cnblogs.com/hunter-w/p/13842751.html
Copyright © 2011-2022 走看看