• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            深入探索C++對象模型讀書筆記 (三)

            Posted on 2010-03-07 16:39 rikisand 閱讀(300) 評論(0)  編輯 收藏 引用 所屬分類: C/C++

            DATA 語義學

            這段代碼輸出什么?

            #include <iostream>
            using namespace std;
            class A{ public:A(){ac='s';}private:char ac;};
            class B:virtual public A{public:B(){a='e';}char a; };
            class C:virtual public A{ };
            class D:public  B,public  C
            {
            public:
                D():A(),B(),C(){b=13;}
                int b;
            };
            int main(){
                D d;
                cout<<"sizeof(A)="<<sizeof(A)<<endl;
                cout<<"sizeof(B)="<<sizeof(B)<<endl;
                cout<<"sizeof(C)="<<sizeof(C)<<endl;
                cout<<"sizeof(D)="<<sizeof(D)<<endl;
                cout<<endl;
                cout<<"address of A's subobject in d"<<(A*)&d<<endl;
                cout<<"address of B's subobject in d"<<(B*)&d<<endl;
                cout<<"address of C's subobject in d"<<(C*)&d<<endl;
                cout<<"address of D's subobject in d"<<(D*)&d<<endl;
                cout<<endl;
                int* p = (int*)(*((int*)&d));
                cout<<"address of b's virtual base table="<<p<<endl;
                cout<<"first member in b's virtual base table="<<*p<<endl;
                cout<<"second member in b's virtual base table="<<*(p+1)<<endl;
                cout<<"third member in b's virtual base table="<<*(p+2)<<endl;
                cout<<endl; 
                p= (int*)*((int*)((C*)&d));
                cout<<"address of c's virtual base class table= "<<p<<endl;
                cout<<"first member in c's virtual base table="<< *p<<endl;
                cout<<"second member in c's virtual base table="<<*(p+1)<<endl;
                cout<<"third member in c's virtual base table="<<*(p+2)<<endl;
                char *pchar= (char*)(&d)+4; //char型加4   注意A中的ac其實是私有變量,B不應該可以訪問到的,實際上通過強制轉換可以非法觸及她-。-
                cout<<*pchar<<endl;
                cout<<*(pchar+12)<<endl;
                B b;
                int *pint =(int*)(&b)+1; //int型+1 
                cout<<*((char*)(pint))<<endl;
                pint = (int*)(&d)+3;
                cout<<*(pint)<<endl;
            }

             

            結果是:

            sizeof(A)=1
            sizeof(B)=9
            sizeof(C)=5
            sizeof(D)=17

            address of A's subobject in d0012FF74
            address of B's subobject in d0012FF64
            address of C's subobject in d0012FF6C
            address of D's subobject in d0012FF64

            address of b's virtual base table=00403350
            first member in b's virtual base table=0
            second member in b's virtual base table=16
            third member in b's virtual base table=0

            address of c's virtual base class table= 00403358
            first member in c's virtual base table=0
            second member in c's virtual base table=8
            third member in c's virtual base table=0
            e
            s
            e
            13

             

            1.語言本身造成的負擔:如virtual baseclass

            2.對齊造成的負擔(對齊會單獨開題討論)

            3.編譯器優化處理 A雖然是空的 but 為了讓A的兩個object在內存中得到不同的地址,編譯器給他加上了一個byte,但是B和C都沒有這一個byte呢?這是編譯器做了優化,允許省掉這一個byte

            看上面的代碼”:

            環境是vs2008 對齊設置為4字節

            A的大小為1 因為有一個char 沒有對齊因為不是結構型對象,如果A沒有這個char大小依然是1的

            B的大小為9 首先開始是它的virtual base class ptr,4個字節的指針,然后是他自己的member 1個char 此時為了保證其對象完整性編譯器對齊到4字節處也就是在第九個字節內放入基類的member

            這樣如果我們把A=B B賦給A,傳輸可以從整4字節開始割出A即可

            C的大小是5 沒什么好解釋

            D的大小是17首先是B的8字節(4字節vbptr+1字節char member+3字節對齊)然后是C的4字節vbptr,然后是自己的member4字節最后是1字節的base class member,可以看到B和C的base class table中的項都是自己位置與這個member的offset 值

             

            不同編譯器可能結果不同的,因為c++ standard 并沒有強制規定 base class subobjects的順序等

             

            data member 是程序執行過程中的某種狀態:

            static data member 是整個class 的狀態

            non-static data member 是個別class-object 的狀態

            c++對象盡量以空間優化和存取速度的考慮來表現non-static members ,并且和c的struct 數據配置的兼容性。

            static data member 放在程序的一個global data segment 中,不會影響個別的class-object 大小

            ,在class沒有object 時已經存在,但是template中有些不同

             

            -----DATA member 的綁定

            始終把nested type 聲明 放在class 起始處,argument list 中的名稱會在第一次遇到時候被適當的決議完成,因此extern 和nested type names 之間的非直覺綁定操作還是會發生。

            ---- DATA 的存取

            Point3d origin,*pt=&origin;

            origin.x = 0.0; 和 pt->x=0.0 ; 有什么區別么??

            如果x是靜態data member 則完全沒有區別 因為他們都在data segment 中和object無關

            ~nonstatic data member---------

            如果point3d不包含虛擬繼承那么沒有差異

            否則我們不能確定pt中必然指向哪一種因此不能在編譯器確定offset需要一些運行時候的計算抉擇,而origin則不同一定是某一個類型的所以沒有問題

            多繼承或者單繼承都不會帶來訪問上的影響,因為他們都可以向c的結構體那樣在編譯時期確定各個member的offset。即使是多繼承pt指向第二個baseclass的data,由于member的位置在編譯時期就已經固定了,因此存取member只是一個offset運算,像單一繼承那樣簡單,不管是指針,reference或者object都一樣

            只有virtual base class 會帶來一些損耗,因為他使得對象模型變得復雜了

            如果我們在一個類中加入了virtual func 會發生什么~~~

            1. 會產生一個virtual table,存放每一個virtual func地址以及rtti支持的type_info

            2.class object 內都加入一個vptr,提供執行期的鏈接

            3.加強ctor 設定vpr初值

            4.加強dtor 消除vptr 從dirived class 到 base class

             

            虛擬繼承:

            他必須支持某種形式的“shared subobject”繼承

            那么一個object會分成一個不變局部和一個共享局部的數據,共享局部就是virtual base class subobject,他的位置會因為每次派生操作發生變化(例如一個virtual base class subobject的位置在不同級別的繼承體系中的位置是不確定的,不像多繼承單繼承那樣有固定的offset),所以他只能間接存取,因此產生了效率缺損.(間接是指的是他只能首先讀出他的指針,然后根據指針的內容取到他)

            所以在虛擬繼承基類中最好不要有data member

            -------指向DATAmember 的指針

            #include <iostream>
            using namespace std;

            class  A
            {
            public:

                int a;
            };
            int main(){
                int  A::* p=&A::a;
                cout<<p<<endl;
            }

            輸出 1

            因為為了防止&A::a和 int A::*a = 0;一樣把他加了1。

             

            虛擬繼承帶來的主要沖擊是,妨礙了優化的有效性,因為每一層虛擬繼承都帶來了一個額外層次的間接性,在編譯器中存取 類似point::x的操作pb.*bx

            會被轉化為 &pb->vbcPoint+bx

            而不是轉換成 &pB +bx

            額外的間接性會降低“把所有操作都搬移到緩存器中執行”優化能力,也就是降低了局部性~

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

            久久综合久久综合久久| 亚洲AV乱码久久精品蜜桃| 国产午夜电影久久| 亚洲精品99久久久久中文字幕 | 国产免费久久精品99久久| 久久久精品久久久久久| 国产aⅴ激情无码久久| 999久久久无码国产精品| 青青热久久国产久精品 | 亚洲狠狠婷婷综合久久蜜芽| 久久久久亚洲AV片无码下载蜜桃| 国产精品亚洲综合专区片高清久久久| 国产色综合久久无码有码| 久久狠狠色狠狠色综合| 国内高清久久久久久| 久久无码精品一区二区三区| 精品无码久久久久久午夜| 最新久久免费视频| 国产精品欧美久久久久无广告 | 久久久久av无码免费网| 国产99久久久国产精免费| 久久一日本道色综合久久| 久久亚洲高清综合| 精品久久久久久无码人妻热 | 伊人热人久久中文字幕| 无码日韩人妻精品久久蜜桃 | A级毛片无码久久精品免费| 久久高潮一级毛片免费| 国产精品成人99久久久久| 久久精品国产亚洲网站| 久久精品国产一区| 亚洲国产成人久久综合碰碰动漫3d | 老司机午夜网站国内精品久久久久久久久| 精品久久久噜噜噜久久久| 欧美牲交A欧牲交aⅴ久久| 性欧美大战久久久久久久久| 日韩人妻无码精品久久免费一| 伊人久久大香线蕉av一区| 亚洲精品美女久久久久99| 久久香蕉超碰97国产精品| 国产V综合V亚洲欧美久久|