日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

operator new,new operator,placement new的区别

發布時間:2024/4/15 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 operator new,new operator,placement new的区别 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

原文地址:http://www.cnblogs.com/jamesmile/archive/2010/04/17/1714311.html,在此感謝

C++中的operator new與new operator,看上去挺像的兩姐妹,卻有天壤之別。

重載的 operator new 必須是類成員函數或全局函數,而不可以是某一名空間
之內的函數或是全局靜態函數。此外,還要多加注意的是,重載 operator new 時需要兼容默
認的 operator new 的錯誤處理方式,并且要滿足 C++ 的標準規定 :當要求的內存大小為 0
byte 時也應該返回有效的內存地址。

?

?

如果使用不同的參數類型重載 operator new/delete,則請采用如下函數聲明形式:
// 返回的指針必須能被普通的 ::operator delete(void*) 釋放
void* operator new(size_t size, const char* file, int line);
// 析構函數拋異常時被調用
void operator delete(void* p, const char* file, int line);
調用時采用以下方式:
string* pStr = new (__FILE, __LINE__) string;
這樣就能跟蹤內存分配的具體位置,定位這個動作發生在哪個文件的哪一行代碼中了。
在“檢測內存錯誤”和“統計內存使用數據”時通常會用這種方式重載。

?

?

operator new

(1) 只分配所要求的空間,不調用相關對象的構造函數。當無法滿足所要求分配的空間時,則

??????? ->如果有new_handler,則調用new_handler,否則

??????? ->如果沒要求不拋出異常(以nothrow參數表達),則執行bad_alloc異常,否則

??????? ->返回0

(2) 可以被重載

(3) 重載時,返回類型必須聲明為void*

(4) 重載時,第一個參數類型必須為表達要求分配空間的大小(字節),類型為size_t

(5) 重載時,可以帶其它參數

new operator

(1) 調用operator new分配足夠的空間,并調用相關對象的構造函數

(2) 不可以被重載

相應地,operator delete與delete operator有相似的特性。

舉個例子

class X?
{
public:
…………
??? static void* operator new(size_t size)
{
??? return ::operator new(size);
}
static void operator delete(void* pointee)
{
??? ::operator delete(pointee);
}
…………
};
X* px = new X();

該行代碼中的new為new operator,它將調用類X中的operator new,為該類的對象分配空間,然后調用當前實例的構造函數。

delete px;

該行代碼中的delete為delete operator,它將調用該實例的析構函數,然后調用類X中的operator delete,以釋放該實例占用的空間。

new operator與delete operator的行為是不能夠也不應該被改變,這是C++標準作出的承諾。而operator new與operator delete和C語言中的malloc與free對應,只負責分配及釋放空間。但使用operator new分配的空間必須使用operator delete來釋放,而不能使用free,因為它們對內存使用的登記方式不同。反過來亦是一樣。

你可以重載operator new和operator delete以實現對內存管理的不同要求,但你不能重載new operator或delete operator以改變它們的行為。

當重載operator new時,可以提供更多的參數,在new一個對象時,通過在關鍵字new后的括號傳遞額外的參數。比如以下的類

class A?
{
public:
??? …………
??? static void* operator new(size_t size, const string& example)
{
??? cout << example << endl;
??? return ::operator new(size);
}
…………
};
A* pa = new (“This will be printed out in operator new”) A();

新標準的C++允許以這樣的方式傳遞一個名為nothrow的參數,以表明當為該對象分配空間失敗時,不拋出異常,而是返回0,以兼容舊標準new的行為。比如

class B {};
B* pb = new (nothrow) B();

當然這只能對那些使用默認operator new操作符的類。對已經重載了operator new的類(比如上面的X和A),如果不聲明能接受nothrow參數,自然無法享受C++標準帶來的禮物

?

operator new的六種重載形式

當寫出
p = new P();
這樣的代碼的時候, 實際上有兩步操作, 首先分配內存,
然后在分配好的內存之上初始化類成員.
第二步是有構造函數完成的, 第一步就是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來實現我們的內存分配方案.

?

?--------------------------------------------

1 #include <iostream> 2 #include <string> 3 #include <crtdbg.h> 4 using namespace std; 5 6 class X 7 { 8 public: 9 X(){cout<<"constructor of X"<<endl;} 10 ~X(){cout<<"deconstructor of X"<<endl;} 11 12 void* operator new(size_t size,string str) 13 { 14 cout<<"operator new size:"<<size<<" with string:"<<str<<endl; 15 return ::operator new(size); 16 } 17 18 void operator delete(void *point) 19 { 20 cout<<"operator delete"<<endl; operator delete(point); 21 //::operator delete(point); 22 } 23 24 private: 25 int num; 26 }; 27 int main(){ 28 X *px = new("A new class") X; 29 delete px; 30 cout<<sizeof("A new class")<<endl; 31 string strd="A new class"; 32 int len = sizeof("A new class"); 33 for (int i = 0;i<len;i++) 34 { 35 cout<<strd[i]; 36 } 37 cout<<"END"; 38 return 0; 39 }

在調用前面的兩個冒號很關鍵,是為了避免進行無限遞歸(沒有它函數將一直調用自己下去)。

關于"::"的小插曲:

?

1 #include <iostream> 2 using namespace std; 3 int n = 12;// A global variable 4 int main() 5 { 6 int n = 13;// A local variable 7 cout << ::n << endl;// Print the global variable: 12 8 cout << n << endl;// Print the local variable: 13 9 }

?

?

?2019-03-06

是否調用構造函數/析構函數

使用new操作符來分配對象內存時會經歷三個步驟:

  • 第一步:調用operator new 函數(對于數組是operator new[])分配一塊足夠大的,原始的,未命名的內存空間以便存儲特定類型的對象。
  • 第二步:編譯器運行相應的構造函數以構造對象,并為其傳入初值。
  • 第三部:對象構造完成后,返回一個指向該對象的指針。

使用delete操作符來釋放對象內存時會經歷兩個步驟:

  • 第一步:調用對象的析構函數。
  • 第二步:編譯器調用operator delete(或operator delete[])函數釋放內存空間。

總之來說,new/delete會調用對象的構造函數/析構函數以完成對象的構造/析構。而malloc則不會。如果你不嫌啰嗦可以看下我的例子:

class A { public: A() :a(1), b(1.11){} private: int a; double b; }; int main() { A * ptr = (A*)malloc(sizeof(A)); return 0; }

在return處設置斷點,觀看ptr所指內存的內容:

可以看出A的默認構造函數并沒有被調用,因為數據成員a,b的值并沒有得到初始化,這也是上面我為什么說使用malloc/free來處理C++的自定義類型不合適,其實不止自定義類型,標準庫中凡是需要構造/析構的類型通通不合適。

而使用new來分配對象時:

int main() { A * ptr = new A; }

查看程序生成的匯編代碼可以發現,A的默認構造函數被調用了:

from this article

?

--------------------------------------------

有關于三者的區別

?

轉載于:https://www.cnblogs.com/guxuanqing/p/4802064.html

總結

以上是生活随笔為你收集整理的operator new,new operator,placement new的区别的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国产精品久久av | 中文字幕av在线播放 | 亚洲综人网 | 色婷婷免费 | 在线99热| 中文在线日本 | 久久综合伊人77777蜜臀 | 男男肉耽高h彩漫 | 毛片视频免费播放 | 国产精品久久久久精 | 精品国产成人av在线免 | 91精品国产91久久久久福利 | www.av在线 | 黑鬼大战白妞高潮喷白浆 | 亚洲最大网站 | 久草青青草 | 日本少妇激情舌吻 | 色欲久久久天天天综合网 | 久久精品9 | 欧美性一区 | 激情视频91| 中文字幕精品一区二区精品 | 爱的色放3| 成人欧美精品一区二区 | 欧美日韩综合在线 | 自拍偷在线精品自拍偷无码专区 | 欧美成人精品欧美一级乱黄 | 伊人论坛 | 成人音影 | 四虎视频国产精品免费 | www精品一区二区三区 | 男女男精品视频网站 | 一区二区三区毛片 | 日韩熟女一区二区 | 免费毛毛片 | 精品久久久久久久久久久久 | 波多野结衣在线观看一区二区 | 老熟妇仑乱视频一区二区 | 欧美人与性动交g欧美精器 国产在线视频91 | 欧美一级高清片 | 岛国av网址 | 日本黄色xxxx| 亚洲色图狠狠干 | 国产成人99 | 精品视频国产 | 国产成人8x视频一区二区 | 亚洲免费av网站 | 亚洲三级在线观看 | 国产对白视频 | a亚洲精品| 美女高潮流白浆视频 | 男女视频免费看 | 九九热这里有精品 | 日本精品视频一区二区 | 亚洲成人中文 | 奇米四色影视 | 中文字幕一区二区三区四区五区 | 91桃色网站 | 亚洲社区一区二区 | 黄色大片免费网站 | 91久久综合 | 96毛片| 亚洲精品图区 | 一区二区在线视频免费观看 | 国内偷拍久久 | 欧美精品一级在线观看 | av网站不卡 | 视频在线观看一区二区 | 91麻豆产精品久久久久久 | 人善交videos欧美3d动漫 | 国产成人精品一二三区 | 久热免费 | 欧美成人自拍视频 | 色国产在线| 爱情岛论坛自拍 | 爽妇网av| 色综合成人 | 国产91视频在线观看 | 亚洲欧美一区二区三区不卡 | 中文字幕午夜 | 日韩爱爱网 | 日本涩涩视频 | 波多野结衣有码 | 亚洲成a人片77777精品 | 日韩精品一区二区三区在线 | 激情四射网 | 欧美熟妇一区二区 | 善良的女邻居在线观看 | 精品国产乱码久久久久久影片 | 性欧美久久 | 久久丫精品久久丫 | 国产www | 国产熟妇久久777777 | 97久久久 | 欧美午夜精品一区二区 | 日韩骚片 | 欧美激情久久久 | 日韩精品无码一本二本三本色 | 午夜极品|