new operator, operator new, placement new

本文參考地址 http://www.cnblogs.com/luxiaoxun/archive/2012/08/10/2631812.html

new operator

就是new 操作符:

  • 調(diào)用 operator new 分配足夠的內(nèi)存空間,調(diào)用對(duì)象的構(gòu)造函數(shù)
  • 不能被重載
operator new

是函數(shù):

  • 只分配內(nèi)存,不調(diào)用構(gòu)造函數(shù)
  • 可以被重載
  • 重載時(shí),返回值類型必須聲明為void *
  • 重載時(shí),第一個(gè)參數(shù)必須是要求分配空間的字節(jié)大小,類型是 size_t
  • 重載時(shí),允許攜帶其他參數(shù)。

例子:

#include <iostream>
#include <string>
using namespace std;

class X{
public:
  X(){
    cout<<"constructor"<<endl;
  }
  
  void* operator new(size_t size, string str){
    cout<< "operator new " << size <<  "  " <<  str << endl;
    return ::operator new(size);
  }   
  void operator delete(void* pointer){
     cout << "operator delete" <<endl;
     ::operator delete(pointer);
  }

  ~X(){
    cout<<"destructor"<<endl;
  }
};

int main(){
  X *x = new ("str") X;
  delete x;
  return 1;
}
placement new

placement new 是重載operator new 的一個(gè)標(biāo)準(zhǔn)、全局的版本,它不能夠被自定義的版本代替(不像普通版本的operator new和operator delete能夠被替換)。原型為:

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

placement new 的執(zhí)行忽略了size_t參數(shù),只返還第二個(gè)參數(shù)。其結(jié)果是允許用戶把一個(gè)對(duì)象放到一個(gè)特定的地方,達(dá)到調(diào)用構(gòu)造函數(shù)的效果。和其他普通的new不同的是,它在括號(hào)里多了另外一個(gè)參數(shù)。

palcement new 存在理由

  • 空間。不分配新的內(nèi)存,而是構(gòu)造一個(gè)新對(duì)象到預(yù)分配的內(nèi)存上。
  • 時(shí)間。new 操作符分配內(nèi)存,需要在堆上查詢足夠大的內(nèi)存空間,而且會(huì)存在不能分配的異常(內(nèi)存不足);placement new 是在已有的內(nèi)存上構(gòu)造對(duì)象,不查找內(nèi)存,分配內(nèi)存的時(shí)間復(fù)雜度為常數(shù),且不存在內(nèi)存分配異常的情況。適合時(shí)間要求高和長(zhǎng)時(shí)間允許不被打斷的程序。

placement 使用需要五步

  • 緩存提前分配,有三種方式:

  • 在堆上進(jìn)行分配class Task :
    char * buff = new [sizeof(Task)];

  • 在棧上進(jìn)行分配class Task:
    char buf[N*sizeof(Task)];

  • 還有一種方式,就是直接通過(guò)地址來(lái)使用。(必須是有意義的地址)

void* buf = reinterpret_cast<void*> (0xF00F);
  • 第二步:對(duì)象的分配
    剛才已分配的緩存區(qū)調(diào)用placement new來(lái)構(gòu)造一個(gè)對(duì)象:
Task *ptask = new (buf) Task
  • 第三步:使用
    按照普通方式使用分配的對(duì)象:
ptask->memberfunction();
ptask->member;
  • 第四步:對(duì)象的析構(gòu)
    一旦你使用完這個(gè)對(duì)象,你必須調(diào)用它的析構(gòu)函數(shù)來(lái)毀滅它。
ptask->~Task(); //調(diào)用外在的析構(gòu)函數(shù)

第五步:釋放
你可以反復(fù)利用緩存并給它分配一個(gè)新的對(duì)象(重復(fù)步驟2,3,4)如果你不打算再次使用這個(gè)緩存,你可以象這樣釋放它:

delete [] buf;

跳過(guò)任何步驟就可能導(dǎo)致運(yùn)行時(shí)間的崩潰,內(nèi)存泄露,以及其它的意想不到的情況。如果你確實(shí)需要使用placement new,請(qǐng)認(rèn)真遵循以上的步驟。

#include <iostream>
using namespace std;

class X
{
public:
    X() { cout<<"constructor of X"<<endl; }
    ~X() { cout<<"destructor of X"<<endl;}

    void SetNum(int n)
    {
        num = n;
    }

    int GetNum()
    {
        return num;
    }

private:
    int num;
};

int main()
{
    char* buf = new char[sizeof(X)];
    X *px = new(buf) X;
    px->SetNum(10);
    cout<<px->GetNum()<<endl;
    px->~X();
    delete []buf;

    return 0;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容