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

            本來想自己總結下operator new相關的,看到周星星同學已經總結得挺全了,直接拿來記錄下(后面綠色部分新加的)。
            轉自
            http://blog.vckbase.com/bruceteen/archive/2009/05/27/37427.html

            1:
            C++標準說:An allocation function shall be a class member function or a global function; a program is ill-formed if an allocation function is declared in a namespace scope other than global scope or declared static in global scope.
            必須是全局函數或類成員函數,而不能是全局之外的名字空間或static全局函數。

            2:new operator的行為
            Foo* p = new Foo;

            ...
            delete p;
            我們知道,上面的代碼,也就是C++中的new操作符(new operator)大致會做下面的事情:
            a.調用operator new, 給對象分配內存
            b.調用Foo的構造函數
            c.返回指針
            ...
            d. 調用Foo的析構函數~Foo()
            e. 調用operator delete釋放內存

            更具體的, new operator的行為如下:
            對于如下代碼:
                Foo* p = new(arg1,arg2,…… ) Foo(para1, para2, ...);
                ...
                delete p;
            編譯器將生成如下代碼:
                調用 p = operator new( size_t 需要的大小,arg1,arg2,…… );  // 分配內存,這里有可能拋出std::bad_alloc,但無須在new operator中捕捉
                如果構造Foo沒有拋出異常                                                    // 即Foo的構造函數后面顯式的聲明了 throw()
                    在p指向處構造foo(para1,para2,……);                              // 調用Foo的構造函數
                    return p;
                否則
                    try
                    {
                        在p指向處構造Foo(para1,para2,……);
                        return p;
                    }
                    catch(...)
                    {
                        調用 operator delete( void* p, arg1,arg2,…… );
                        throw;
                    }
                ...
                調用 Foo的析構函數~Foo();
                調用 operator delete( void* p );

            從上面的步驟可以看出:
            (1)對于operator new, 我們只要確保第一參數是表示申請內存的大小, 其他參數可以自己隨意重載
            (2)只有Foo構造失敗(構造函數內拋出異常),我們的operator delete( void* p, arg1,arg2,…… )才會被調用,否則只會調用operator delete( void* p )

            3:全局形式的operator new偽代碼
            void* operator new( size_t size ) // 包括其他形式
            {
                if( 0 == size ) // 須要注意
                    size = 1;

                while(1)
                {
                    分配size字節內存;
                    if(分配成功)
                        return 指向內存的指針;

                    new_handler globalhandler = set_new_handler(0);
                    set_new_handler(globalhandler);

                    if( globalhandler )
                        (*globalhandler)();
                    else
                        throw std::bad_alloc();
                }
            }
            void operator delete( void* raw )
            {
                if( 0 == raw ) // 須要注意
                    return;
                ...
            }
            須要說明的是,編譯器本身就隱含著一個 void* operator new( size_t ),所以重載全局operator new必須加其他參數以示區別。
            一般重載分配函數時都會重載三個,分別是 void* operator new( size_t, …… ),void operator delete( void*, …… ),以及一般形式的 void operator delete( void* )。

            4. set_new_handler的作用
                set_new_handler設置一個函數,此函數將在分配內存失敗時被調用,見3中的代碼。
                從3中的代碼還能看得出,new_handler必須有主動退出的功能,否則就會導致operator new內部死循環。因此newhandler的一般形式是:
                void mynewhandler()
                {
                    if( 有可能使得operator new成功(比如釋放部分內存) )
                    {
                        做有可能使得operator new成功的事
                        return;
                    }
                    // 主動退出
                    或 abort/exit 直接退出程序
                    或 set_new_handler(其他newhandler);
                    或 set_new_handler(0)
                    或 throw bad_alloc()或派生類 // 這一種比較好,不粗魯的關閉程序,也不更改其他設置
                }
            須要說明的是,沒有類形式的set_new_handler,但這也無所謂,你可以自己寫。(見《Effective C++ 2e》條款7)

            5. 類形式的operator new偽代碼:
            struct base
            {
                ...
                static void* operator new( size_t size );
                static void operator delete( void* raw );
            };
            void* base::operator new( size_t size )
            {
                if( sizeof(base) != size ) // 須要注意
                    return ::operator new(size);

                類似于3 // 注意“沒有類形式的set_new_handler”
            }
            void base::operator delete( void* raw )
            {
                if( sizeof(base) != size ) // 須要注意
                {
                    ::operator delete(raw);
                    return;
                }
                同3
            }

            6. operator new的函數類型:
            對我們來說一般有3種是語言要求的標準operator new(plain new, nothrow new, placement new):
            void *operator new(std::size_t count) throw(std::bad_alloc);             //一般的版本(plain new)
            void *operator new(std::size_t count,  const std::nothrow_t&) throw();    //兼容早版本, new內存分配失敗不會拋出異常(nothrow new)
            void *operator new(std::size_t count, void *ptr) throw();  //placement版本(placement new)

            上面的方法我們可以這樣調用:
            Foo* p = new Foo;
            delete p;

            Foo* p1 = new(std::nothrow) Foo;
            delete p1;

            Foo f;
            Foo* p2 = new(&f) Foo;
            p2->~Foo();

            針對數組則是:
            void *operator new[](std::size_t count) throw(std::bad_alloc);            
            void *operator new[](std::size_t count,  const std::nothrow_t&) throw();    
            void *operator new[](std::size_t count, void *ptr) throw();  

            可以看到上面函數第一個都是對象空間大小,除了重載C++中operator new的標準類型,另外我們也可以重載其他類型的operator new, 比如
            void *operator new(std::size_t count, const string& s) throw(std::bad_alloc);  
            void *operator new[](std::size_t count, const string& s) throw(std::bad_alloc); 

            然后就可以這樣調用了: string str("abc"); Foo* p = new(str) Foo;

            當然,如果我們自己重寫了operator new, 最好我們也重寫operator delete,這樣如果我們的構造函數里拋出異常,我們自己重寫的operator delete會被調用。(當然,如果構造對象成功,最后delete時只會調用operator delete( void* p ))

            比如針對上面新加的operator new函數,新加operator delete如下:
            void operator delete(void* p, const string& s) throw();
            void operator delete[](void* p, const string& s) throw();
            可以看到,自己新加的operator delete, 只需確保第一個參數內存指針。

            7. new operator和operator new的區別

                  new operator就象sizeof一樣是語言內置的,我們不能改變它的含義,它的功能總是一樣的。它要完成的功能分成兩部分。第一部分是分配足夠的內存以便容納所需類型的對象。第二部分是它調用構造函數初始化內存中的對象。new operator總是做這兩件事情,你不能以任何方式改變它的行為。

              我們所能改變的是如何為對象分配內存。new operator調用一個函數來完成必需的內存分配,你能夠重寫或重載這個函數來改變它的行為。new operator為分配內存所調用函數的名字是operator new。

                  如果想在堆上建立一個對象,應該用new operator。它既分配內存又為對象調用構造函數。如果你僅僅想分配內存,就應該調用operator new函數;它不會調用構造函數。如果你想定制自己的在堆對象被建立時的內存分配過程,你應該寫你自己的operator new函數,然后使用new operator,new operator會調用你定制的operator new。如果你想在一塊已經獲得指針的內存里建立一個對象,應該用placement new。
                  與new operator/operator new相對應的是delete operator/operator delete, 當我們調用delete operator時,實際上包含析構函數調用和通過operator delete釋放內存2個階段。
               我們可以單純的通過operator new 和 operator delete來分配和釋放內存:
                void *buffer = operator new(50*sizeof(char)); // 內存以容納50個char, 沒有調用構造函數
              ...
              operator delete(buffer); // 釋放內存, 沒有調用析構函數

            8. operator new的一些原則:
            a. 一般不要重寫全局的operator new, 具體可以參考 不要重載全局 ::operator new
            b. 如果重載了operator new, 同時提供所有版本(plain new, nothrow new, placement new)
            c. 成對的提供new和delete, 即如果重載了operator new, 同時重載operator delete

             

            posted on 2012-10-06 22:25 Richard Wei 閱讀(2761) 評論(0)  編輯 收藏 引用 所屬分類: C++
            久久亚洲国产午夜精品理论片 | 国产亚洲美女精品久久久| 久久青草国产精品一区| 久久久久久久国产免费看| 亚洲∧v久久久无码精品| 91麻精品国产91久久久久| 99精品久久精品一区二区| 日韩亚洲欧美久久久www综合网| 伊人情人综合成人久久网小说| 青青青国产成人久久111网站| 久久综合色老色| 国产精品女同一区二区久久| 久久久久亚洲Av无码专| 欧美久久一区二区三区| 久久最近最新中文字幕大全 | 久久精品99无色码中文字幕| 亚洲精品无码久久久久久| 久久国产精品波多野结衣AV| 国产精品久久毛片完整版| 一本久久知道综合久久| 午夜视频久久久久一区 | 久久婷婷成人综合色综合| 香蕉99久久国产综合精品宅男自| 久久九九全国免费| 久久久久亚洲av无码专区导航| 国内精品综合久久久40p| 午夜精品久久久久成人| 久久久人妻精品无码一区| 品成人欧美大片久久国产欧美...| 99久久婷婷免费国产综合精品| 久久久噜噜噜www成人网| 亚洲愉拍99热成人精品热久久| 久久综合亚洲鲁鲁五月天| 蜜桃麻豆WWW久久囤产精品| 久久强奷乱码老熟女网站| 久久精品亚洲精品国产欧美| 精品国产91久久久久久久a| 色综合久久综精品| 久久精品国产福利国产琪琪| 久久精品无码一区二区app| 久久久久久亚洲精品不卡|