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

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

            1:
            C++標(biāo)準(zhǔn)說: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.
            必須是全局函數(shù)或類成員函數(shù),而不能是全局之外的名字空間或static全局函數(shù)。

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

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

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

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

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

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

                    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;
                ...
            }
            須要說明的是,編譯器本身就隱含著一個(gè) void* operator new( size_t ),所以重載全局operator new必須加其他參數(shù)以示區(qū)別。
            一般重載分配函數(shù)時(shí)都會(huì)重載三個(gè),分別是 void* operator new( size_t, …… ),void operator delete( void*, …… ),以及一般形式的 void operator delete( void* )。

            4. set_new_handler的作用
                set_new_handler設(shè)置一個(gè)函數(shù),此函數(shù)將在分配內(nèi)存失敗時(shí)被調(diào)用,見3中的代碼。
                從3中的代碼還能看得出,new_handler必須有主動(dòng)退出的功能,否則就會(huì)導(dǎo)致operator new內(nèi)部死循環(huán)。因此newhandler的一般形式是:
                void mynewhandler()
                {
                    if( 有可能使得operator new成功(比如釋放部分內(nèi)存) )
                    {
                        做有可能使得operator new成功的事
                        return;
                    }
                    // 主動(dòng)退出
                    或 abort/exit 直接退出程序
                    或 set_new_handler(其他newhandler);
                    或 set_new_handler(0)
                    或 throw bad_alloc()或派生類 // 這一種比較好,不粗魯?shù)年P(guān)閉程序,也不更改其他設(shè)置
                }
            須要說明的是,沒有類形式的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的函數(shù)類型:
            對我們來說一般有3種是語言要求的標(biāo)準(zhǔn)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內(nèi)存分配失敗不會(huì)拋出異常(nothrow new)
            void *operator new(std::size_t count, void *ptr) throw();  //placement版本(placement new)

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

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

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

            針對數(shù)組則是:
            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();  

            可以看到上面函數(shù)第一個(gè)都是對象空間大小,除了重載C++中operator new的標(biāo)準(zhǔn)類型,另外我們也可以重載其他類型的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); 

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

            當(dāng)然,如果我們自己重寫了operator new, 最好我們也重寫operator delete,這樣如果我們的構(gòu)造函數(shù)里拋出異常,我們自己重寫的operator delete會(huì)被調(diào)用。(當(dāng)然,如果構(gòu)造對象成功,最后delete時(shí)只會(huì)調(diào)用operator delete( void* p ))

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

            7. new operator和operator new的區(qū)別

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

              我們所能改變的是如何為對象分配內(nèi)存。new operator調(diào)用一個(gè)函數(shù)來完成必需的內(nèi)存分配,你能夠重寫或重載這個(gè)函數(shù)來改變它的行為。new operator為分配內(nèi)存所調(diào)用函數(shù)的名字是operator new。

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

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

             

            posted on 2012-10-06 22:25 Richard Wei 閱讀(2764) 評論(0)  編輯 收藏 引用 所屬分類: C++
            亚洲乱码精品久久久久..| 久久精品国产免费观看三人同眠| 国产精品免费久久久久久久久| 久久久精品视频免费观看| 一本久久免费视频| 狠狠久久亚洲欧美专区| 久久婷婷国产剧情内射白浆| 国产精品久久久久影视不卡| 亚洲国产精品综合久久网络 | 国产精品女同一区二区久久| 久久人妻无码中文字幕| 国产精品成人99久久久久 | av无码久久久久久不卡网站| 亚洲?V乱码久久精品蜜桃 | 99久久免费只有精品国产| 18岁日韩内射颜射午夜久久成人| 国产免费久久精品99久久| 久久婷婷五月综合97色 | 国产精品久久久久乳精品爆| 99久久精品免费看国产一区二区三区 | 久久精品国产91久久麻豆自制| 2021国内久久精品| 久久午夜福利电影| 国内精品久久久久国产盗摄| 精品一区二区久久| 国产产无码乱码精品久久鸭| 影音先锋女人AV鲁色资源网久久| 久久国产精品一区| 精品综合久久久久久97超人| 久久久一本精品99久久精品88| 午夜精品久久久久| 中文字幕久久亚洲一区| 欧美精品丝袜久久久中文字幕| 国产成人精品久久| 国産精品久久久久久久| 国内精品久久久久久久亚洲| 中文字幕一区二区三区久久网站| 国产精品久久精品| 久久九九亚洲精品| 国产高潮久久免费观看| 久久久久97国产精华液好用吗|