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

            黎明的剔透里伸出了你沁清的曖昧

            Graphics|EngineDev|GameDev|2D&3D Art

              C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
              60 隨筆 :: 1 文章 :: 18 評論 :: 0 Trackbacks
            C++中new的3種形態:
            new operator 
            operator new 
            placement new


            new operator:
            new操作符,像 + - * / && . :: ?: 等操作符一樣,是語言內置的, 它不能被重載,不能改變其行為。
            它的行為包括分配內存的 operator new 和調用構造函數的 placement new。
            new operator 實際上做了三件事:獲得一塊內存空間、調用構造函數、返回正確的指針。如果創建的是簡單類型(如char)的變量,那么第二步會被省略。
            比如:
            CTest* pT = new CTest(22);
            它的調用實際上等效于:
            void*  p  = operator newsizeof(CTest) );//operator new分配內存
            CTest* pT = new(p) CTest(22);//placement new調用構造函數,并返回正確的CTest*指針


              
            operator new:
            原型為: void* operator new(size_t size);
            它分配指定大小的內存, 可以被重載, 可以添加額外的參數, 但第一個參數必須為 size_t 。
            它除了被 new operator 調用外也可以直接被調用, 如: 
            void* p = operator new(sizeof(CTest));

            這種用法和調用 malloc 一樣, 只分配了sizeof(CTest)大小的內存.



            placement new:
            置換new,它在一塊已經指定的內存上調用構造函數, 包含頭文件<new>之后也可以直接使用,
            如:
                     
            CTest* pT = new(p) CTest(22);
            它在p這塊內存上調用CTest的構造函數來初始化CTest。
            這個函數返回一個對象指針,對象是在傳遞進來的p這塊內存上分配的,也就說指定一個額外的自變量(p)作為new operator "隱式調用operator new"時所用,
            于是被調用的operator new 除了接受"一定得有的size_t"這個自變量外,還需要接受一個void *的指針,指向一塊內存,準備用來接受構造函數好的對象,這樣operator new就
            是所謂的placement new,其operator new定義如下:

            void * operator new(size_t,void *location){
                 
            return loaction;
            }
            所以operator new的目的就是為對象找到一塊內存,然后返回一個指針指向它.在placement new的情況下,調用者已經知道指向內存的指針,因為調用者知道對象應該放哪,
            因此placement new唯一需要做的就是將它獲得的指針再返回,至于沒有用到(但一定得有的)size_t參數,所以不賦予名稱,以免編譯器發出"某物未被使用"的警告。
            如果用 placement new 構造出來的對象,必須顯示的調用對象的析構函數,
            如:     
            pT->~CTest();
            然后釋放內存存, 調用 operator delete (對應于分配時的 operator new)operator delete(pT);




             
            小結:

            1)、想在堆上建立一個對象,應該用 new 操作符,它既分配內存又為對象調用構
                    造函數。

            2)、如果僅僅想分配內存,就應該調用 operator new 函數;它不會調用構造函數。
                
            3)、如果想定制在堆對象被建立時的內存分配過程,應該重載 operator new 函數,
                    然后使用 new operator,new operator 會調用定制的 operator new 。

            4)、如果想在一塊已經獲得指針的內存里建立一個對象,應該用 placement new 。 
            placement new 主要適用于:
                   (a): 對時間要求非常高的應用程序中,因為這些程序分配的時間是確定的;
                   (b): 長時間運行而不被打斷的程序;
                   (c): 以及執行一個垃圾收集器 (garbage collector) 。

            注意:如果用 placement new 構造出來的對象,必須顯示的調用對象的析構函數。


            程序示例:
             1 #include <iostream>
             2 using namespace std;
             3 #include <new>
             4 
             5 
             6 class CTest{
             7 public:
             8     CTest(int _x, int _y){
             9         X = _x;
            10         Y = _y;
            11     }
            12     ~CTest(){
            13         X = 0;
            14         Y = 0;
            15     }
            16     void Test(char* sz){
            17         cout<<sz<<":"<<"  "<<"X="<<X<<"   "<<"Y="<<Y<<endl;
            18     }
            19     int X;
            20     int Y;
            21 };
            22 
            23 //new operator:
            24 void F1(){
            25     CTest* pT = new CTest(11);             // new operator
            26     
            27     pT->Test("F1");
            28 
            29     delete pT;
            30 
            31 }
            32 
            33 
            34 //    operator new
            35 //    placement new
            36 
            37 void F2(){
            38     void*  p  = operator new(sizeof(CTest)); // operator new : 分配內存
            39     CTest* pT = new(p) CTest(22);          // placement new: 構造對象
            40     
            41     pT->Test("F2");
            42     
            43     pT->~CTest();                            // 必須顯示析構對象
            44     operator delete(pT);                     // operator delete: 釋放內存
            45 }
            46 
            47 
            48  //   也可這樣實現:
            49 void F3(){
            50     char*  p  = new char[sizeof(CTest)]; // new operator: char為內置類型,不會調用構造函數,相當于只分配內存
            51 
            52     CTest* pT = new(p) CTest(33);      // placement new: 在這塊內存上構造CTest對象
            53     
            54     pT->Test("F3");
            55     
            56     pT->~CTest();                        // 必須顯示析構CTest對象
            57 
            58     delete [] p;                         // delete operator: char為內置類型,不會調用析構函數,相當于只釋放內存
            59 }
            60 
            61 
            62 void main(){
            63     F1();
            64     F2();
            65     F3();
            66 } 
            F1:  X=1   Y=1
            F2:  X=2   Y=2
            F3:  X=3   Y=3
            Press any key to continue


             
            C++中的delete:
            為了避免resource leaks,每一個動態分配行為都應該必須匹配一個相應但相反的釋放動作;
            如果你寫:
            string *ps;
            delete ps;//使用delete operator;相對與 new operator
            指向delete ps;要求編譯器既能夠析構ps所指的對象,又能夠釋放被該對象占用的內存,
            其中釋放內存是由operator delete所執行的(相對于 operator new),其聲明如下:

            void operator delete(void *memoryTOBeDeallocated);

            因此執行delete ps; 那么編譯器就產生了如下代碼:
            ps->~string();               //調用對象的析構函數dtoroperator
            operator delete(ps);       //釋放對象所占的內存

            這里呈現的一個暗示就是:若果你打算處理原始的、未設置初值的內存,應該完全回避new operator和delete operator ,改調用operator new 取得內存,operator delete歸還系統內存
            void *buffer=operator new(50*sizeif(char)); // 分配內存相當于C語言中的malloc

            operator delete(buffer);       //釋放內存 但沒用調用任何析構函數 相當于C語言中的free

            如果你使用了placement new在某塊內存上產生對象,你應該避免對那塊內存使用delete operator,這是因為delete operator會調用operator delete來釋放內存,但是該內存內含的對象最初并非是由operator new分配的,畢竟placement new只返回它所接受的指針而已,但不知道這個指針是從哪里來的,所以為了抵消該對象的構造函數的影響,你應該直接調用該對象的析構函數

            class Widget{
            public:
                Widget(
            int WidgetSize);
                
            };

            Widget
            * constructWidgetInBUuffer(void *buffer,int WidgetSize){
                    
            return new(buffer) Widget(WidgetSize);
            }
            //以下函數用來分配及釋放shared memory中的內存
            void *mallocShared(size_t size);
            void freeShared(void *memory);

            void *sharedMemory=mallocShared(sizeof(Widget));

            Widget 
            *pw=constructWidgetInBUuffer(sharedMemory,10);//運用placement new

            delete pw;
            //無定義??!,因為sharedMemory來自mallocShared,不是來自operator new

            pw
            ->~Widget();//OK!!析構pw所指的Widget對象,但未釋放Widget對象的內存

            freeShared(pw);
            //OK!!  釋放pw所指的內存 不用調用任何析構函數








            posted on 2011-10-30 00:22 情絕格調(fresmaster) 閱讀(422) 評論(0)  編輯 收藏 引用 所屬分類: Coding
            久久人人爽人人爽人人片AV高清| 亚洲午夜精品久久久久久人妖| 亚洲午夜无码AV毛片久久| 亚洲国产一成久久精品国产成人综合 | 18岁日韩内射颜射午夜久久成人| 99久久www免费人成精品| 一本久久综合亚洲鲁鲁五月天亚洲欧美一区二区| 久久这里都是精品| 亚洲国产精品久久| 久久这里只有精品首页| 精品久久久久久综合日本| 中文成人无码精品久久久不卡| 色欲综合久久中文字幕网| 国产精品伊人久久伊人电影 | avtt天堂网久久精品| 国产亚洲色婷婷久久99精品91| 中文字幕久久久久人妻| 精品多毛少妇人妻AV免费久久| 新狼窝色AV性久久久久久| 亚洲伊人久久成综合人影院 | 久久综合色区| 精品国产综合区久久久久久| 97久久久精品综合88久久| 伊人久久综合成人网| 亚洲一级Av无码毛片久久精品| 丁香久久婷婷国产午夜视频| 狠狠色丁香久久综合婷婷| 久久国产精品无码HDAV| 久久婷婷人人澡人人爽人人爱| 久久久久人妻精品一区三寸蜜桃| 国产精品久久99| AV无码久久久久不卡蜜桃| 69国产成人综合久久精品| 人人狠狠综合久久88成人| 久久综合88熟人妻| 99久久777色| 国产成人综合久久综合| 欧美综合天天夜夜久久| 国产成人久久精品麻豆一区| 久久高潮一级毛片免费| 亚洲精品高清一二区久久|