C++-new 的六種重載形式


當寫出這樣的代碼的時候, 實際上有兩步操作:

p = new P();

  1.分配內存,
  2.然后在分配好的內存之上初始化類成員.

第二步是有構造函數完成的, 第一步就是new函數的工作.

全局的new有六種重載形式, 

void *operator new(std::size_t count)
    throw(std::bad_alloc);             //一般的版本

void *operator new(std::size_t count,  //兼容早版本的new
    const std::nothrow_t&) throw();    //內存分配失敗不會拋出異常

void *operator new(std::size_t count, void *ptr) throw();
                                       //placement版本
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();

  所以, 剛才的用法, 就是使用new函數的一種重載形式.
  如果A這個對象以同樣實行重載了new函數的化, 作為成員函數會被優先調用.

C++的各種new簡介

1.new T

  第一種new最簡單,調用類的(如果重載了的話)或者全局的operator new分配空間,然后用類型后面列的參數來調用構造函數,用法是

new TypeName(initial_args_list)

  如果沒有參數,括號一般可以省略。例如:

int *p=new int;
int *p=new int(10);
int *p=new foo("hello");


  通過調用delete來銷毀:

delete p;


2. new T[]
  這種new用來創建一個動態的對象數組,他會調用對象的operator new[]來分配內存(如果沒有則調用operator new,搜索順序同上),然后調用對象的默認構造函數初始化每個對象。
  
  用法:

new TypeName[num_of_objects];


  例如:

int *p= new int[10];


  銷毀時使用

operator delete[]


3.new()T 和new() T[]
  這是個帶參數的new,這種形式的new會調用operator new(size_t,OtherType)來分配內存這里的OtherType要和new括號里的參數的類型兼容。
  這種語法通常用來在某個特定的地址構件對象,稱為placement new,前提是operator new(size_t,void*)已經定義,通常編譯器已經提供了一個實現,包含<new>頭文件即可,這個實現只是簡單的把參數的指定的地址返回,因而new()運算符就會在括號里的地址上創建對象。

  需要說明的是,第二個參數不是一定要是void*,可以識別的合法類型,這時候由C++的重載機制來決定調用那個operator new。

  當然,我們可以提供自己的operator new(size_,Type),來決定new的行為,比如

char data[1000][sizeof(foo)];
inline void* operator new(size_t ,int n)
{
        return data[n];
}


  就可以使用這樣有趣的語法來創建對象:

foo *p=new(6) foo(); //把對象創建在data的第六個單元上


  標准庫還提供了一個nothrow的實現:

void* operator new(std::size_t, const std::nothrow_t&) throw();
void* operator new[](std::size_t, const std::nothrow_t&) throw();

 


  就可以實現調用new失敗時不拋出異常

new(nothrow) int(10);
// nothrow 是std::nothrow_t的一個實例

  placement new 創建的對象不能直接delete來銷毀,而是要調用對象的析夠函數來銷毀對象,至於對象所占的內存如何處理,要看這塊內存的具體來源。

4. operator new(size_t)
  這個的運算符分配參數指定大小的內存並返回首地址,可以為自定義的類重載這個運算符,方法就是在類里面聲明加上

void *operator new(size_t size)
{
        //在這里分配內存並返回其地址
}


  無論是否聲明,類里面重載的各種operator new和operator delete都是具有static屬性的一般不需要直接調用operator new,除非直接分配原始內存(這一點類似於C的malloc),在沖突的情況下要調用全局的operator加上::作用域運算符:

::operator new(1000); // 分配1000個字節


  返回的內存需要回收的話,調用對應的operator delete

5.operator new[](size_t)

  這個也是分配內存,,只不過是專門針對數組,也就是new T[]這種形式,當然,需要時可以顯式調用

6.operator new(size_t size, OtherType other_value)
  和operator new[](size_t size, OtherType other_value)
  參見上面的new()
  需要強調的是,new用來創建對象並分配內存,它的行為是不可改變的,可以改變的是各種operator new,我們就可以通過重載operator new來實現我們的內存分配方案.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM