• <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>

            執(zhí)行期語義學(xué) RunTime Semantics

            if( yy == xx.getValue() ) …

            X xx; Y yy;

            class Y{

            public:

            Y();  ~Y();  bool operator == (constY& )const;

            };

            class X{

            public:

            X(); ~X(); operator Y()const; //重載轉(zhuǎn)換類型操作符 必須成員不能有參數(shù)不能有返回值詳細(xì)在 http://www.shnenglu.com/zqsand/archive/2010/03/15/109748.html里面有介紹

            X getValue();

            };

            看看上面的表達(dá)式怎么執(zhí)行的~~~

            首先等號運(yùn)算符的參數(shù)確定  if(yy.operator==(xx.getValue()));

            Y的== 需要一個(gè)Y型的參數(shù),但是getvalue得到的是一個(gè)X型的,如果沒有X到Y(jié)的轉(zhuǎn)型方法,這個(gè)式子是錯(cuò)的~ 而恰好X有個(gè)類型轉(zhuǎn)換符~

            if(yy.operator == (xx.getValue().operator Y()))

            增加的代碼都是編譯器默默為我們加上的~~~

            注意在這個(gè)過程中,我們需要一個(gè)臨時(shí)的Xobject 儲(chǔ)存 getValue返回值 X temp1 = xx.getValue()

            一個(gè)class Y object 儲(chǔ)存 operator Y()返回值 Y temp2 = temp1.operator Y();

            一個(gè) int 放置 等號返回值  int tmp3 = yy.operator == (temp2);

            最后析構(gòu)函數(shù)會(huì)實(shí)施在每一個(gè)臨時(shí)class object上.

            所以,我們的代碼變成:

            {

            X temp1 = xx.getValue();Y temp2 = temp1.operator Y();int tmp3 = yy.operator == (temp2);

            if(tmp3)  dosth```

            tmp2.Y::~Y();

            tmp1.X::~X();

            }

            surprise~~-----------------------------------------------------------------------

            6.1-對象的構(gòu)造和析構(gòu)

            ·一般來說,dtor會(huì)被放在每一個(gè)離開點(diǎn)(object 還存活)之前 ,所以,如果一個(gè)區(qū)段或者函數(shù)有多個(gè)離開點(diǎn),那么每一個(gè)return 離開點(diǎn)都要插入一個(gè)dtor了。因此我們一般盡量放置object在使用它的程序區(qū)段附近,節(jié)省不必要的對象產(chǎn)生與摧毀操作。

            ·全局對象:全局對象如果有ctor或者dtor的話需要靜態(tài)的初始化操作和內(nèi)存釋放操作。c++中全局對象放在data segment中,如果不明確指定值,內(nèi)存內(nèi)容為0.

            但是ctor必須等到程序startup后才能實(shí)施。由于必須對一個(gè)放在datasegment 中的object初始化表達(dá)式evaluate ,所以object需要靜態(tài)初始化

            一種策略(cfont 的 munch)

            為每一個(gè)需要靜態(tài)初始化的檔案產(chǎn)生一個(gè)  _sti()函數(shù),內(nèi)帶必要的ctor調(diào)用操作或者inline expansions。 類似的產(chǎn)澀會(huì)給你一個(gè)std()函數(shù)調(diào)用dtor

            一個(gè)_main()函數(shù)調(diào)用sti 一個(gè) exit()函數(shù)調(diào)用_std()

            然后cfont在我們的程序中安插對 _main _exit 的調(diào)用。 最后需要解決的是如何收集各個(gè)對象的sti和std。cfont使用了nm命令 , 打印出符號表格(目標(biāo)文件的符號表),然后munch會(huì)搜索所有用sti或者std開頭的目標(biāo)函數(shù),把他們記錄到一個(gè)表格,當(dāng)main和exit調(diào)用時(shí)候便利表格即可。

            修改版本的方法是:system V中,coff格式的目標(biāo)文件,檢驗(yàn)可執(zhí)行文件,找出有著_linknodes并且內(nèi)帶一個(gè)指針指向 sti 和std函數(shù)的文件,把他們都串聯(lián)起來,接下來把鏈表頭結(jié)點(diǎn)設(shè)置為一個(gè)全局的_head object (定義在新的 patch runtime library),這個(gè)library中有一種不同的_main _exit 他們會(huì)以head為起點(diǎn),遍歷鏈表,調(diào)用sti和std。

            實(shí)際上現(xiàn)在的ELF格式,有init 和.fini兩個(gè)section,完成靜態(tài)初始化和釋放操作。編譯器設(shè)定的startup函數(shù)會(huì)完成平臺(tái)特定的支持

            virtual base class 的指針或者引用存取virtual base class subobject,是一種只有在執(zhí)行期才能加以確定的操作。所以,編譯器需要支持class object 的靜態(tài)初始化,至少涵蓋object的指針和reference。

            局部靜態(tài)對象

            const Matrix& identity(){

                static Matrix mat_identity;

                return mat_identity;

            }

            mat_identity的ctor必須只執(zhí)行一次,mat_identity的dtor必須只執(zhí)行一次

            編譯器只在identity被調(diào)用的時(shí)候才構(gòu)造mat_identity,這樣避免如果不被調(diào)用也需要構(gòu)造所有對象。同時(shí)編譯器引入條件式解析~也就是如果構(gòu)造了則解析之

            對象數(shù)組:

            Points knots[10];

            如果Points沒有定義ctor和dtor只要分配空間即可

            如果有default ctor ,ctor必須實(shí)施于每個(gè)元素身上~這是由runtime library 完成的。 cfont中 我們使用vec_new()函數(shù)  MS和Sun提供兩個(gè)函數(shù),一個(gè)用來處理 vbs的class 一個(gè)處理內(nèi)帶base class 的class,后者為 vec_vnew() 函數(shù)原型基本如下

            void* vec_new(void *array,size_t elem_size,int elem_count,void (*ctor)(void*),void(*dtor)(void*,char)))

            array如果是0,數(shù)組由new分配與heap, vec_new(&knots,sizeof(Point),10,&Point::Point,0);

            6.2 new 和 delete 運(yùn)算符

            int *pi  = new int(5);

            執(zhí)行步驟:

            int* pi = __new (sizeof(int));

            *pi = 5;

            int *pi;

            if(pi = __new(sizeof(int)))

               *pi=5;

            delete pi;

            if(pi!=0)

            __delete (pi);

            注意pi并不會(huì)自動(dòng)清除為0!

            CTOR

            Point3d * origin=new Point3d;

            if(origin = __new(sizeof(Point3d))){

            try{

               origin = Point3d::Point3d(origin);   

            }

            calch(…){

            __delete(origin);

            throw;//上傳exception

            }

            }

            DTOR

            delete origin;

            if(origin!=0){

              Point3d::~Point3d(origin);

               __delete(origin);

            }

            一種library對new的設(shè)計(jì):~~

            extern void* operator new(size_t size){

            if(size==0)size=1;

            void *last_alloc;

            while(!(last_alloc=malloc(size))){

            if(_new_handler) (*_new_handler)();

            else return 0;

            }

            return last_alloc;

            }

            雖然new T[0];是合法的,但是語言要求每次對new的調(diào)用必須返回一個(gè)獨(dú)一無二的指針,解決該問題的傳統(tǒng)方法是傳回一個(gè)指針,指向默認(rèn)為1byte的內(nèi)存區(qū)塊。所以size被設(shè)為1.然后這種設(shè)計(jì)允許使用者提供一個(gè)屬于自己的_new_handler() 函數(shù)。

            extern void operator delete (void *ptr) { if(ptr)free (char*)ptr;}

            針對數(shù)組的new 語義:

            int *p_array = new int[5];

            這時(shí)候 vec_new()不會(huì)真正調(diào)用,因?yàn)椋闹饕δ苁前裠efault ctor 實(shí)施于class object數(shù)組的每個(gè)元素身上。new運(yùn)算符會(huì)被調(diào)用:

            int *p_array = (int*) __new(5*sizeof(int));

            如果數(shù)組的class object 有default ctor vec_new才會(huì)被調(diào)用。

            Point3d *p_array = new Point3d[10];編譯成:

            Point3d *p_array = vec_new(0,sizeof(Point3d),10,&point3d::Point3d,&Point3d::~Point3d);

            個(gè)別數(shù)組構(gòu)造如果exception發(fā)生,dtor被傳輸給vec_new ,已經(jīng)構(gòu)造的object需要dtor 實(shí)施。

            delete 時(shí)候,開始需要程序員指定大小,后來編譯器開始不適用程序員指定的,而是只需要寫delete [] ptr 即可。

            如何記錄數(shù)組大小呢:

            一種方法在vecnew返回的內(nèi)存塊配置一個(gè)額外的word,大小放在其中。

            如果

            class Point {public:virtual ~Point (){}};

            class Point3d : public Point {public:virtual ~Point3d(){}};

            如果Point *ptr = new Point3d[10];

            當(dāng)我們delete [] ptr;時(shí)候只有 Point::~Point被掉用````

            在vc里敲了代碼驗(yàn)證確實(shí)如此~~~

            實(shí)施于數(shù)組上的dtor是根據(jù)交給vec_delete()函數(shù)的被刪除指針類型的dtor,也就是point的dtor,每一個(gè)元素大小也被一起傳了過去。

            如何避免:

            避免一個(gè)base class 指針指向一個(gè)derived class 的數(shù)組。如果真的要這么寫看代碼吧

            class point{
            public:
                int p;
                point(){cout<<"point ctor"<<endl;}
                ~point(){cout<<"point dtor"<<endl;}
            };
            class point3d:public point{
            public:
                int q;
                point3d(){cout<<"point3d ctor"<<endl;}
                ~point3d(){cout<<"point3d dtor"<<endl;}
            };
            int main()
            {   
                 point *ptr = new point3d[3];
                 //delete [] ptr; 這樣寫是不行的

                 //要這樣寫
                 for(int i=0;i<3;i++){
                     point3d * p=&((point3d*)ptr)[i]; //恢復(fù)成point3d數(shù)組指針
                     delete p;
                 }
            }

            Placement Operator New

            有一個(gè)重載過的new 運(yùn)算符 需要兩個(gè)參數(shù),類型為void*

            Point2w *ptw = new(area) Point2w;

            其中area指向內(nèi)存一個(gè)區(qū)塊,用來放置產(chǎn)生出來的Point2w object.這個(gè)預(yù)先定義好的placement operator new 實(shí)現(xiàn)方法: 將獲得的指針arena 所指的地址傳回即可

            void* operator new (size_t,void* p) {return p;}

            事實(shí)上,他執(zhí)行的另一半工作是:把point2w 的ctor 實(shí)施于 arena所指的地址上

            Point2w *ptw = (Point2w *)arena; if(ptw!=0)ptw->Point2w::Point2w();

            -------

            p2w->~Point2w;

            p2w = new(arena)Point2w;

            如果我們用

            delete p2w; p2w = new(arena) Point2w;

            delete會(huì)釋放p2w指向的內(nèi)存 由于下一指令還要用到p2w,我們應(yīng)該調(diào)用dtor并保留存儲(chǔ)空間,以便再次使用.

            還有一些關(guān)于placement opeator new 的設(shè)計(jì)問題··沒看明白 不記了··

            6.3臨時(shí)對象 :

            c++對臨時(shí)對象并無硬性規(guī)定,由編譯器抉擇。

            實(shí)際上 T c = a+ b; T operator + (const T& ,const T&);

            a+b可以直接構(gòu)建于c上

            那么根本不產(chǎn)生臨時(shí)對象

            但是,意義相當(dāng)?shù)?c=a+b;不能忽略臨時(shí)對象":

            T temp; temp=operator+(a,b);c.operator =(tmp);tmp.T::~T();

            注意c=a+b;中,直接傳遞c進(jìn)入operator 中,也就是不要tmp的話:由于operator函數(shù)不為其外加參數(shù)調(diào)用dtor(期望一個(gè)新鮮的內(nèi)存),所以必須在其調(diào)用前調(diào)用dtor.然而轉(zhuǎn)換操作會(huì)變成c.T::~T();c.T::T(a+b);copy ctor dtor  copy assignment operator 都可以自定義,所以我們用 析構(gòu)和拷貝構(gòu)造代替賦值一般而言是不安全的,所以需要臨時(shí)對象調(diào)用operator=

            所以 T c=a+b;比 c=a+b;更有效率

            臨時(shí)對象生命周期:

            臨時(shí)對象被摧毀,應(yīng)該是對完整表達(dá)式求職過程的最后一個(gè)步驟,該完整表達(dá)式造成臨時(shí)對象的產(chǎn)生

            如果一個(gè)臨時(shí)對象綁定在一個(gè)reference上,對象將殘留,知道被初始化之reference生命結(jié)束,或者知道臨時(shí)對象的聲明范疇結(jié)束。

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

             

            久久久国产精品网站| 久久久久久伊人高潮影院| 久久婷婷五月综合97色一本一本 | 久久se精品一区二区影院 | 国产亚洲美女精品久久久久狼| 久久久噜噜噜www成人网| 精品久久久久久久无码 | 久久久国产亚洲精品| 久久久久亚洲精品天堂| 国产精品美女久久久久AV福利 | 日韩久久久久中文字幕人妻| 久久99免费视频| 色婷婷噜噜久久国产精品12p| 久久人妻AV中文字幕| 久久久久亚洲av成人无码电影 | 国产欧美久久久精品影院| 熟妇人妻久久中文字幕| 久久91精品国产91久| 久久久久久国产精品免费免费 | 一本大道加勒比久久综合| 新狼窝色AV性久久久久久| 亚洲精品乱码久久久久久蜜桃图片| 久久久久久国产a免费观看不卡| 观看 国产综合久久久久鬼色 欧美 亚洲 一区二区 | 狠狠色丁香婷婷久久综合| 激情综合色综合久久综合| 日韩影院久久| 无码国产69精品久久久久网站| 久久亚洲美女精品国产精品| 久久精品亚洲精品国产色婷| 国产精品视频久久| 久久精品国产一区二区三区不卡 | 女人高潮久久久叫人喷水| 欧美久久久久久| 久久免费精品一区二区| 亚洲国产精品无码久久青草| 一级做a爰片久久毛片看看| 99久久精品免费看国产一区二区三区| 久久久久久精品久久久久| 91精品国产91久久久久久蜜臀| 老司机午夜网站国内精品久久久久久久久 |