當寫出這樣的代碼的時候, 實際上有兩步操作:
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來實現我們的內存分配方案.