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

歡迎訪問 生活随笔!

生活随笔

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

c/c++

C++ 内存基本构件new/delete的意义、运用方式以及重载方式

發布時間:2023/12/1 c/c++ 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++ 内存基本构件new/delete的意义、运用方式以及重载方式 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

  • 一、對new的理解
    • 1、new做了什么
    • 2、new被編譯器轉為了什么
    • 3、operate_new源代碼長啥樣
  • 二、對delete的理解
    • 1、delete做了什么
    • 2、delete被編譯器轉為了什么
    • 3、operator delete源代碼長啥樣
  • 三、構造函數與析構函數的直接調用
  • 參考

一、對new的理解

1、new做了什么

C++告訴我們,new的時候會分配一塊內存用來放對象,分配好之后會調用構造函數。所以說所謂的自動調用,其實是被new調用的。
所以總結new做的動作:1、分配內存 2、調用構造函數

2、new被編譯器轉為了什么

以下面語句為例:

Complex* pc = new Complex(1,2);

仿造編譯器的流程,可以具化為:

try{//1、allocatevoid* mem = operate_new(sizeof(Complex));//2、cast,將指針轉型為Complex*類型指針pc = static_cast<Complex*>(mem);//3、construct,注意這種寫法只有編譯器才能使用,我們需要避免這種行為pc->Complex::Complex(1,2); } catch(std::bad_alloc){//若allocation失敗就不執行構造函數 }

注意第3點,如果想要直接調用ctor,可以使用placement new:

new(p)Complex(1,2);

3、operate_new源代碼長啥樣

這里截取的是vc98版本的源代碼:

可見,如果分配內存成功,就返回分配到的內存的指針,否則陷入while循環中。
什么時候會失敗?大量耗用內存之后,我們需要new一個對象,會發現我們調用不到內存了。
這時會使用callnewh函數,即調用newhandle函數,這是一種自設定的函數。也就是說,分配內存失敗就會調用你設定的那個函數。我們需要在newhandle函數中釋放內存,以便調用完newhandle函數后會有內存給malloc分配。
關于函數的第二個參數
nothrow與異常的拋出有關,它是不拋異常,意思是說operate_new這個函數是
保證不拋異常的
,在新版的C++特性中,不拋異常的寫法有做修改。
它的解釋如下:
struct std::nothrow_t {};

The struct is used as a function parameter to operator new to indicate that the function should return a null pointer to report an
allocation failure, rather than throw an exception.

二、對delete的理解

1、delete做了什么

C++告訴我們,delete的時候會先調用析構函數,然后調用delete函數釋放內存。

2、delete被編譯器轉為了什么

先調用delete函數:

Complex* pc = new Complex(1,2); ... delete pc;

被編譯器轉為:

pc->~Complex(); //先析構,注意這里可以直接調用析構函數 operator delete(pc); //然后釋放內存

3、operator delete源代碼長啥樣

也就是直接調用free函數。

總結一下,new與delete調用的是operate_new和operator delete。而operate_new調用的是malloc函數,operator delete調用的是free函數。

三、構造函數與析構函數的直接調用

先通過指針調用構造函數,這里先選擇string類,因為string在標準庫里面是個typedefine,本名為basic_string。編譯器把第一個string換成了basic_string,后面再找string沒有找到,所以這里會報錯。這個并不是真正不能使用構造函數的原因。
例1:

string* pstr = new string;cout << "str= " << *pstr << endl;//! pstr->string::string("jjhou"); //[Error] 'class std::basic_string<char>' has no member named 'string' //! pstr->~string(); //crash -- 其語法語意都是正確的, crash 只因為上一行被 remark 起來嘛. cout << "str= " << *pstr << endl;

例2:
可以看到在GCC里面通過指針或者直接調用構造函數是不正確的,在VC中,條件會放寬。

class A { public:int id;A() : id(0) { cout << "default ctor. this=" << this << " id=" << id << endl; }A(int i) : id(i) { cout << "ctor. this=" << this << " id=" << id << endl; }~A() { cout << "dtor. this=" << this << " id=" << id << endl; } };A* pA = new A(1); //ctor. this=000307A8 id=1cout << pA->id << endl; //1 //! pA->A::A(3); //in VC6 : ctor. this=000307A8 id=3//in GCC : [Error] cannot call constructor 'jj02::A::A' directly//! A::A(5); //in VC6 : ctor. this=0013FF60 id=5// dtor. this=0013FF60 //in GCC : [Error] cannot call constructor 'jj02::A::A' directly// [Note] for a function-style cast, remove the redundant '::A'cout << pA->id << endl; //in VC6 : 3//in GCC : 1 delete pA; //dtor. this=000307A8

參考

https://www.bilibili.com/video/BV1Kb411B7N8?p=7

總結

以上是生活随笔為你收集整理的C++ 内存基本构件new/delete的意义、运用方式以及重载方式的全部內容,希望文章能夠幫你解決所遇到的問題。

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