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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

【C++ Primer | 19】控制内存分配

發布時間:2023/11/30 c/c++ 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【C++ Primer | 19】控制内存分配 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1. 測試代碼:?

#include <iostream> #include <new> #include <cstring> #include <cstdlib> using namespace std;void* operator new(size_t size) {cout << "global Override operator new" << endl;if (void* ptr = malloc(size)) return ptr;elsethrow bad_alloc(); }void* operator new(size_t size, int flag) {cout << "global Override operator new: " << flag << endl;return (::operator new(size)); }void operator delete (void* ptr) {cout << "global Override operator delete" << endl;free(ptr);ptr = nullptr; }void operator delete (void* ptr, int flag) {cout << "Override operator delete: " << flag << endl;::operator delete(ptr);ptr = nullptr; }int main() {int* ptr = new int(10);delete ptr;cout << endl << "------------" << endl << endl;ptr = new(20) int(10);delete ptr;return 0; }

輸出結果:

分析:

從上面的結果可以看出,new int(10);直接先調用 operator new(size_t size); 由于int沒有構造函數,在那塊內存上調用int的構造函數; 在delete ptr; 的時間直接調用 operator delete(void * ptr);這個函數

當new(20) int(10);的時候,則調用重載版本的 operator new(size_t size, int flag); 而該函數有調用了 operator new(size_t size); 函數,釋放的時候delete ptr;還是直接只調用operator delete(void * ptr);(注:這里初步提出為啥不調用operator delete(void * ptr, int flag); 這個函數來釋放ptr ???因為它的用途不在這,而在于下面將要講的。

?

2. 測試代碼:

#include <iostream> #include <new> #include <cstring> #include <cstdlib> using namespace std;void* operator new(size_t size) {cout << "global Override operator new" << endl;void* ptr = malloc(size);return ptr; }void* operator new(size_t size, int flag) {cout << "global Override operator new: " << flag << endl;return (::operator new(size)); }void operator delete (void* ptr) {cout << "global Override operator delete" << endl;free(ptr);ptr = nullptr; }void operator delete (void* ptr, int flag) {cout << "Override operator delete: " << flag << endl;::operator delete(ptr);ptr = nullptr; }class Base { public:Base(){cout << "Base construct" << endl;throw 2;}~Base(){cout << "Base destructor" << endl;}//類中定制的operator new會覆蓋全局的函數,但可以通過簡單的調用全局的函數來實現調用static void* operator new(size_t size){cout << "operator new of Base" << endl;return ::operator new(size); //調用全局的operator new}static void* operator new(size_t size, int flag){cout << "Override operator new of Base: " << flag << endl;return operator new(size);}static void operator delete(void* ptr){cout << "Operator delete of Base" << endl;::operator delete(ptr);}static void operator delete(void* ptr, int flag){cout << "Override operator delete of Base: " << flag << endl;operator delete(ptr);}int x;int y; }; int main() {try{Base* bptr = new(20) Base;}catch (...){cout << "catch a exception" << endl;}return 0; }

輸出結果:

?

2. 若是不給Base類重載?static void operator delete(void * ptr, int flag);這個函數,結果則如下圖:

#include <iostream> #include <new> #include <cstring> #include <cstdlib> using namespace std;void* operator new(size_t size) {cout << "global Override operator new" << endl;void* ptr = malloc(size);return ptr; }void* operator new(size_t size, int flag) {cout << "global Override operator new: " << flag << endl;return (::operator new(size)); }void operator delete (void* ptr) {cout << "global Override operator delete" << endl;free(ptr);ptr = nullptr; }void operator delete (void* ptr, int flag) {cout << "Override operator delete: " << flag << endl;::operator delete(ptr);ptr = nullptr; }class Base { public:Base(){cout << "Base construct" << endl;throw 2;}~Base(){cout << "Base destructor" << endl;}//類中定制的operator new會覆蓋全局的函數,但可以通過簡單的調用全局的函數來實現調用static void* operator new(size_t size){cout << "operator new of Base" << endl;return ::operator new(size); //調用全局的operator new}static void* operator new(size_t size, int flag){cout << "Override operator new of Base: " << flag << endl;return operator new(size);}static void operator delete(void* ptr){cout << "Operator delete of Base" << endl;::operator delete(ptr);}int x;int y; }; int main() {try{Base* bptr = new(20) Base;}catch (...){cout << "catch a exception" << endl;}return 0; }

輸出結果:

?

?

二、定位new表達式

operator new和operator delete和alloctor類的allocate和deallocate很像,都是負責分配和釋放內存的函數,但是對于operator new分配的內存空間我們無法使用construct函數構造對象,我們應該使用new的定位new形式構造對象。

1. 測試代碼:

#include <iostream> #include <new> using namespace std;const int chunk = 16; class Foo { public:int val() { return _val; }Foo() { _val = 0; } private:int _val; };//預分配內存,但沒有Foo對象 char* buf = new char[sizeof(Foo) * chunk]; int main(void) {//在buf中創建一個Foo對象Foo* pb = new (buf) Foo;//檢查一個對象是否被放在buf中if (pb->val() == 0){cout << "new expressio worked!" << endl;}//到這里不能再使用pbdelete[] buf;return 0; }

placement new的作用就是:創建對象但是不分配內存,而是在已有的內存塊上面創建對象。用于需要反復 創建并刪除的對象上,可以降低分配釋放內存的性能消耗。定位new表達式(placement new expression),允許程序員將對象創建在已經被分配好的內存中,new表的式的形式如下:

new (place_address) type new (palce_address) type (initializer-list)

【Note】:?

  • 當只傳入一個指針類型的實參時,定位new表達式構造對象但是不分配內存,這個指針沒有要求,甚至可能是一個不是一個指向動態內存的指針
  • 調用析構函數會銷毀對象,但是不會釋放內存。

?

2. 測試代碼:

#include <iostream> using namespace std; char addr1[100]; int main() {cout << "******定位new表達式演示***by David***" << endl;char addr2[100];char *addr3 = new char[100];cout << "addr1 = " << (void*)addr1 << endl;cout << "addr2 = " << (void*)addr2 << endl;cout << "addr3 = " << (void*)addr3 << endl;int *p = nullptr;p = new(addr1)int; 把內存分配到靜態區*p = 1;cout << (void*)p << " " << *p << endl;p = new(addr2)int; 把內存分配到棧區*p = 2;cout << (void*)p << " " << *p << endl;p = new(addr3)int; //把內存分配到堆區*p = 3;cout << (void*)p << " " << *p << endl;return 0; }

輸出結果:

?

參考資料

  • 定制自己的new和delete:operator new 和 operator delete
  • 特殊的工具和技術
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的【C++ Primer | 19】控制内存分配的全部內容,希望文章能夠幫你解決所遇到的問題。

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