欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136

專注電子技術學習與研究
當前位置:單片機教程網 >> MCU設計實例 >> 瀏覽文章

C++中類的內存空間大小(sizeof)分析

作者:龔平   來源:本站原創   點擊數:  更新時間:2014年03月13日   【字體:

    在C語言中存在關于結構體的存儲空間大小是比較深入的話題,其中涉及計算機的基本原理、操作系統等。我認為對齊是C語言中讓很多初學者都拿不準摸不透的問題,特別是在跨平臺的情況下,對齊這種問題更加的復雜多變,每一種系統都有自己獨特的對齊方式,在Windows中經常是以結構體重最大內置類型的存儲單元的字節數作為對齊的基準,而在Linux中,所有的對齊都是以4個字節對齊。
 
    那么在C++中的類的內存空間大小又有哪些特殊的問題呢?
    首先,我認為對齊肯定也是其中的問題之一,對齊主要是為了加快讀取的速度。
    關于對齊這個我認為基本上已經是操作系統內定好的,既然Linux與Windows存在差別,那么在C++的類中,關于對齊肯定也會存在一定的差別。關于對齊我認為只要記住平時使用的系統的對齊準則就可以了,即:在Windows中經常是以結構體重最大內置類型的存儲單元的字節數作為對齊的基準,而在Linux中,所有的對齊都是以4個字節對齊。
  
    其次,我認為就應該討論在基類中哪些成員占有存儲空間,那些成員不占用內存空間?
    在C++中占存儲區間的主要是非static的數據對象,主要包括各種內置的數據類型,類對象等,類中的函數聲明以及函數定義都不算內存空間。但是需要注意所有的virtual函數(虛函數)共享一段內存區域,一般來說是4個字節。為什么只是包含非static數據對象呢?因為static數據并不屬于類的任何一個對象,它是類的屬性,而不是具體某一個對象的屬性,在整個內存區域中只有一個內存區域存儲對應的static數據,也就是所有的類對象共享這個數據,所以不能算做具體某一個對象或者類型的內存空間。
    因此可以認為基類對象的存儲空間大小為:
    非static數據成員的大小 + 4 個字節(虛函數的存儲空間)
    當然這個大小不是所有數據成員大小的疊加,而是存在一個對齊問題,具體的應該參考相關的對齊文章。

 
    最后,我認為肯定要關心一下派生類的存儲空間了?
    在C++中,繼承類是一個比較有用的類,繼承使得各種類在基類的基礎上擴展,這時候派生類中包含了基類的信息,一般而言,在基類中存在虛函數時,派生類中繼承了基類的虛函數,因此派生類中已經繼承了派生類的虛函數。因此繼承類中不能再添加虛函數的存儲空間(因為所有的虛函數共享一塊內存區域),而僅僅需要考慮派生類中心添加進來的非static數據成員的內存空間大小。
    因此可以認為派生類對象的存儲空間大小為:
    基類存儲空間 + 派生類特有的非static數據成員的存儲空間
 
   還有一類是比較特殊的情況,如果是虛繼承的情況下,這時的存儲空間大小就會發生變化。
    基類的存儲空間 + 派生類特有的非static數據成員的存儲空間 + 每一個類的虛函數存儲空間。
  
    下面我采用一些例子說明上面的問題:
    對齊的問題:

    class test
    {
    public:
            test();
    private:
            int a;
            char c;
    };

    cout << sizeof(test) << endl;

  上面的代碼在linux以及windows下都會輸出8,而不是輸出5,這個是在C語言中已經討論過的話題,但是說明對齊在C++中也是要考慮的。關于操作系統的差異在后面用一個統一的例子說明。
    虛函數問題
    為了討論虛函數,我們在test類中添加一個虛析構函數,然后再測試結果。  

    class test
    {
    public:
            test();
            virtual ~test();
    private:
            int a;
            char c;
    };
    cout << sizeof(test) << endl;

這段代碼與前面的代碼沒有什么區別,只是添加了一個虛函數,然后編譯調試,這時候輸出的結果12,也就是說增加了一個虛函數以后,類的數據成員增加了4個字節,那么是否是每一個虛函數都占有4個字節呢?其實是不會的,在test中加入一個新的虛函數virtual void get_a_c(),這時在輸出的結果還是12,這說明所有的虛函數共享4個字節。
    static數據
    我們知道static數據是非對象的屬性,而是類的屬性,他不能算是某一個對象或者類型的存儲空間,在類定義中只能聲明,初始化只能在類外執行,當然有例外的。這也不做分析了。具體參看后面的大例子。
    派生類的存儲空間
    派生類從基類中繼承了很多成員,自己也會增加很多的成員,由于虛函數也會被繼承下來,所以就是在派生類中不顯式定義虛函數,在派生類中也會存在從基類繼承下來的虛函數,因此虛函數不需要額外計算內存空間,而只需要增加基類的非static成員數據大小。定義如下面所示,該函數會輸出20,剛好是添加的非static數據double d的存儲空間大小。證明了上面的分析。

    class test
    {
    public:
            test();
            virtual ~test();
            virtual void get_a_c();
    private:
            int a;
            char c;
    };

    class derived_test:public test
    {
    public:
            virtual ~derived_test();
    private:
            double d ;
    };

    cout << sizeof(derived_test) << endl;

測試虛繼承的類的大小:

    class A
    {
            char i[3];
    public:
            virtual void a(){};
    };

    class B : public virtual A
    {
            char j[3];
    public:
            virtual void b(){}
    };

    class C: public virtual B
    {
            char k[3];
    public:
            virtual void c(){}
    };

    int main()
    {
        cout << "sizeof(A): " << sizeof(A) << endl;
        cout << "sizeof(B): " << sizeof(B) << endl;
        cout << "sizeof(C): " << sizeof(C) << endl;
        return 0;
    }

下面采用一個比較綜合的例子說明一下操作系統以及各種綜合的影響分析。

    #include <iostream>
    #include <string>
    #include <vector>

    class test
    {
    public:
        test();
        virtual ~test();
        virtual void get_a_c();
    private:
        int a;
        char c;
    };

    class derived_test:public test
    {
    public:
        virtual ~derived_test();
    private:
        double d ;
    };

    class base
    {
    private:
        char a;
        static int refrence_count;
        std::string name;
        double price;
        std::vector<double> dvec;
    public:
        base();
        virtual ~base();
        static int get_count();
    };

    int base::get_count()
    {
        return refrence_count;
    }

    int base::refrence_count = 0;

    class new_base
    {
    private:
        char a;
        double price;
        std::vector<double> dvec;
        std::string name;
        static int refrence_count;
    public:
        new_base();
        virtual ~new_base();
        static int get_count();
    };

    int new_base::get_count()
    {
        return refrence_count;
    }
    int new_base::refrence_count = 0;

    class derived: public base
    {
    private:
        int min_qty;
        double discount;
        static int newp;
    public:
        derived();
        virtual ~derived(){};
    };

    class new_derived:public new_base
    {
    private:
        double discount;
        int min_pty;
        static int newp;
    public:
        new_derived();
        virtual ~new_derived(){}
    };

    int main()
    {
        std::cout << "The size of test is " << sizeof(test) << std::endl;
        std::cout << "The size of derived_test is " << sizeof(derived_test) << std::endl;
        std::cout << "The size of base is " << sizeof(base) << std::endl;
        std::cout << "The size of new_base is " << sizeof(new_base) << std::endl;
        std::cout << "The size of derived is " << sizeof(derived) << std::endl;
        std::cout << "The size of new_derived is " << sizeof(new_derived) << std::endl;
       
        return 0;
    }

上面在windows和linux的結果分別如下:
windows:

Linux:

從上面的結果可以之知道在兩個系統下,結果是不一樣的。說明操作系統也對類的存儲空間大小有較大的影響。

關閉窗口

相關文章