最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

淺析C++ new的三種面貌

 更新時(shí)間:2020年08月24日 14:55:09   作者:Dabelv  
這篇文章主要介紹了C++ new的三種面貌,幫助大家更好的理解和學(xué)習(xí)c++,感興趣的朋友可以了解下

1.new的三種面貌

C++中使用new運(yùn)算符產(chǎn)生一個(gè)存在于Heap(堆)上對(duì)象時(shí),實(shí)際上調(diào)用了operator new()函數(shù)和placement new()函數(shù)。在使用new創(chuàng)建堆對(duì)象時(shí),我們要清楚認(rèn)清楚new的三種面貌,分別是:new operator、operator new()和placement new()。

1.1new operator

new operator是C++保留的關(guān)鍵字,我們無(wú)法改變其含義,但我們可以改變new完成它功能時(shí)調(diào)用的兩個(gè)函數(shù),operator new()和placement new()。也就是說(shuō)我們?cè)谑褂眠\(yùn)算符new時(shí),其最終是通過(guò)調(diào)用operator new()和placement new()來(lái)完成堆對(duì)象的創(chuàng)建工作。使用new operator時(shí),其完成的工作有如下三步:

因此,當(dāng)我們經(jīng)常按照如下方式使用new operator時(shí):

string* sp=new string(“hello world”);

實(shí)際上等價(jià)于:

//第一步:申請(qǐng)?jiān)伎臻g,行為類似于malloc
void* raw=operator new(strlen(“hello world”));
//第二步:通過(guò)placement new調(diào)用string類的構(gòu)造函數(shù),初始化申請(qǐng)空間
new (raw) string(“hello world”);
//第三部:返回對(duì)象指針
string* sp=static_cast<string*>(raw);

1.2operator new()

operator new()用于申請(qǐng)Heap空間,功能類似于C語(yǔ)言的庫(kù)函數(shù)malloc(),嘗試從堆上獲取一段內(nèi)存空間,如果成功則直接返回,如果失敗則轉(zhuǎn)而去調(diào)用一個(gè)new handler,然后拋出一個(gè)bad_alloc異常。operator new()的函數(shù)原型一般為

void* operator new (std::size_t size) throw (std::bad_alloc);

具體實(shí)現(xiàn)如下:

void *__CRTDECL operator new(size_t size) throw (std::bad_alloc)
{    
  // try to allocate size bytes
  void *p;
  while ((p = malloc(size)) == 0)   //申請(qǐng)空間
    if (_callnewh(size) == 0)    //若申請(qǐng)失敗則調(diào)用處理函數(shù)
    {    
      // report no memory
      static const std::bad_alloc nomem;
      _RAISE(nomem);        //#define _RAISE(x) ::std:: _Throw(x) 拋出nomem的異常
    }
  return (p);
}

注意:

(1)函數(shù)后添加throw表示可能會(huì)拋出throw后括號(hào)內(nèi)的異常;
(2)operator new()分為全局和類成員。當(dāng)為類成員函數(shù)時(shí),使用new產(chǎn)生類對(duì)象時(shí)調(diào)用的則是其成員函數(shù)operator new()。如果要重載全局的operator new會(huì)改變所有默認(rèn)的operator new的方式,所以必須要注意。正如new與delete相互對(duì)應(yīng),operator new與operator delete也是一一對(duì)應(yīng),如果重載了operator new,那么理應(yīng)重載operator delete。

placement new():

一般來(lái)說(shuō),使用new申請(qǐng)空間時(shí),是從系統(tǒng)的堆中分配空間,申請(qǐng)所得空間的位置根據(jù)當(dāng)時(shí)內(nèi)存實(shí)際使用情況決定。但是,在某些特殊情況下,可能需要在程序員指定的特定內(nèi)存創(chuàng)建對(duì)象,這就是所謂的“定位放置new”(placement new)操作。placement new()是一個(gè)特殊的operator new(),因?yàn)槠涫莖perator new()函數(shù)的重載版本,只是取了個(gè)別名叫作placement new罷了。作用是在已經(jīng)獲得的堆空間上調(diào)用類構(gòu)造函數(shù)來(lái)初始化對(duì)象,也就是定位構(gòu)造對(duì)象。通常情況下,構(gòu)造函數(shù)是由編譯器自動(dòng)調(diào)用的,但是不排除程序員手動(dòng)調(diào)用的可能性,比如對(duì)一塊未初始化的內(nèi)存進(jìn)行處理,獲得想要的對(duì)象,這是需要求助于placement new()。placement new()是C++標(biāo)準(zhǔn)庫(kù)的一部分,被申明在頭文件<new>中,其函數(shù)原型是:

void* operator new(std::size_t, void* __p);

具體實(shí)現(xiàn)如下:

void* operator new(std::size_t, void* __p) throw()
{
  return __p;
}

注意:

(1)placement new()的函數(shù)原型不是void* placement new(std::size_t, void* __p) ;
(2)placement new只是operator new()的一個(gè)重載,多了一個(gè)已經(jīng)申請(qǐng)好的空間,由void* __p指定;
(3)用法是new (addr) constructor(),對(duì)addr指定的內(nèi)存空間調(diào)用構(gòu)造函數(shù)進(jìn)行初始化。為何稱為placement new,從其用法可以看出只是用于調(diào)用構(gòu)造函數(shù)。

定位放置new操作的語(yǔ)法形式不同于普通的new操作。例如,一般都用如下語(yǔ)句A* p=new A;申請(qǐng)空間,而定位放置new操作則使用如下語(yǔ)句A* p=new (ptr) A;申請(qǐng)空間,其中ptr就是程序員指定的內(nèi)存首地址??疾烊缦鲁绦?。

#include <iostream>
using namespace std;

class A{
  int num;
public:
  A(){
    cout<<"A's constructor"<<endl;
  }

  ~A(){
    cout<<"~A"<<endl;
  }
  void show(){
    cout<<"num:"<<num<<endl;
  }
};

int main(){
  char mem[100];
  mem[0]='A';
  mem[1]='\0';
  mem[2]='\0';
  mem[3]='\0';
  cout<<(void*)mem<<endl;
  A* p=new (mem) A;
  cout<<p<<endl;
  p->show();
  p->~A();
  getchar();
}

程序運(yùn)行結(jié)果:

0024F924
A's constructor
0024F924
num:65
~A

閱讀以上程序,注意以下幾點(diǎn)。

(1)用定位放置new操作,既可以在棧(stack)上生成對(duì)象,也可以在堆(heap)上生成對(duì)象。如本例就是在棧上生成一個(gè)對(duì)象。

(2)使用語(yǔ)句A* p=new (mem) A;定位生成對(duì)象時(shí),指針p和數(shù)組名mem指向同一片存儲(chǔ)區(qū)。所以,與其說(shuō)定位放置new操作是申請(qǐng)空間,還不如說(shuō)是利用已經(jīng)請(qǐng)好的空間,真正的申請(qǐng)空間的工作是在此之前完成的。

(3)使用語(yǔ)句A *p=new (mem) A;定位生成對(duì)象是,會(huì)自動(dòng)調(diào)用類A的構(gòu)造函數(shù),但是由于對(duì)象的空間不會(huì)自動(dòng)釋放(對(duì)象實(shí)際上是借用別人的空間),所以必須顯示的調(diào)用類的析構(gòu)函數(shù),如本例中的p->~A()。

(4)萬(wàn)不得已才使用placement new,只有當(dāng)你真的在意對(duì)象在內(nèi)存中的特定位置時(shí)才使用它。例如,你的硬件有一個(gè)內(nèi)存映像的I/O記時(shí)器設(shè)備,并且你想放置一個(gè)Clock對(duì)象在哪那個(gè)位置。

總結(jié):

(1)若想在堆上建立一個(gè)對(duì)象,應(yīng)該用new操作符。它既分配內(nèi)存又調(diào)用其構(gòu)造函數(shù)進(jìn)行初始化。
(2)若僅僅想分配內(nèi)存,應(yīng)該調(diào)用operator new(),他不會(huì)調(diào)用構(gòu)造函數(shù)。若想定制自己在堆對(duì)象被建立時(shí)的內(nèi)存分配過(guò)程,應(yīng)該重寫自己的operator new()。
(3)若想在一塊已經(jīng)獲得的內(nèi)存空間上建立一個(gè)對(duì)象,應(yīng)該用placement new。雖然在實(shí)際開發(fā)過(guò)程中,很少需要重寫operator new(),使用內(nèi)置的operator new()即可完成大部分程序所需的功能。但知道這些,有助于一個(gè)C++程序猿對(duì)C++內(nèi)存的管理有個(gè)清楚的認(rèn)識(shí)。

2.了解delete和operator delete()

為了避免內(nèi)存泄漏,每個(gè)動(dòng)態(tài)內(nèi)存分配必須與一個(gè)等同相反的 deallocation 對(duì)應(yīng)。數(shù)operator delete與delete操作符的關(guān)系與operator new與new操作符是一樣的。delete用于使用使用new申請(qǐng)的空間,operator delete用于釋放operator new申請(qǐng)的空間(類似于malloc與free),那誰(shuí)來(lái)清理placement new初始化的內(nèi)存內(nèi)容呢?唯一辦法就是調(diào)用對(duì)象的析構(gòu)函數(shù)。

示例代碼:

string* sp=new string(“hello world”);
delete sp;

第一行代碼在上文已經(jīng)剖析,那么當(dāng)調(diào)用delete sp時(shí),發(fā)生了什么?

delete sp等價(jià)于:

ps->~string(); //用于清理內(nèi)存內(nèi)容,對(duì)應(yīng)placement new
operator delete(ps);//釋放內(nèi)存空間,對(duì)應(yīng)于operator new()

其中operator delete()的函數(shù)原型為:

void operator delete(void *memoryToBeDeallocated);

以上就是淺析C++ new的三種面貌的詳細(xì)內(nèi)容,更多關(guān)于C++ new的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C語(yǔ)言中g(shù)etchar()與putchar()函數(shù)詳解

    C語(yǔ)言中g(shù)etchar()與putchar()函數(shù)詳解

    本文主要介紹了C語(yǔ)言中g(shù)etchar()與putchar()函數(shù)詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-01-01
  • C語(yǔ)言實(shí)現(xiàn)統(tǒng)計(jì)一行字符串的單詞個(gè)數(shù)

    C語(yǔ)言實(shí)現(xiàn)統(tǒng)計(jì)一行字符串的單詞個(gè)數(shù)

    這篇文章主要介紹了C語(yǔ)言實(shí)現(xiàn)統(tǒng)計(jì)一行字符串的單詞個(gè)數(shù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • C語(yǔ)言中sizeof()與strlen()的區(qū)別詳解

    C語(yǔ)言中sizeof()與strlen()的區(qū)別詳解

    這篇文章主要給大家介紹了關(guān)于C語(yǔ)言中sizeof()與strlen()區(qū)別的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • VC實(shí)現(xiàn)獲取當(dāng)前正在運(yùn)行的進(jìn)程

    VC實(shí)現(xiàn)獲取當(dāng)前正在運(yùn)行的進(jìn)程

    這篇文章主要介紹了VC實(shí)現(xiàn)獲取當(dāng)前正在運(yùn)行的進(jìn)程,涉及VC針對(duì)系統(tǒng)進(jìn)程的相關(guān)操作技巧,需要的朋友可以參考下
    2015-05-05
  • 如何高效移除C++關(guān)聯(lián)容器中的元素

    如何高效移除C++關(guān)聯(lián)容器中的元素

    關(guān)聯(lián)容器和順序容器有著很大不同,關(guān)聯(lián)容器中的元素是按照關(guān)鍵字來(lái)保存和訪問的,而順序容器中的元素是按它們?cè)谌萜髦械奈恢脕?lái)順序保存和訪問的,本文介紹了如何高效移除C++關(guān)聯(lián)容器中的元素的方法,需要的朋友可以參考下
    2025-04-04
  • C++中各種初始化方式示例詳解

    C++中各種初始化方式示例詳解

    這篇文章主要給大家介紹了關(guān)于C++中各種初始化方式的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用C++具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-10-10
  • 使用C++的ORM框架QxORM詳解

    使用C++的ORM框架QxORM詳解

    這篇文章主要介紹了使用C++的ORM框架QxORM的相關(guān)知識(shí),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-06-06
  • C++11關(guān)于auto關(guān)鍵字的使用示例

    C++11關(guān)于auto關(guān)鍵字的使用示例

    今天小編就為大家分享一篇關(guān)于C++11關(guān)于auto關(guān)鍵字的使用示例,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2018-12-12
  • C++中菱形繼承的解釋與處理詳解

    C++中菱形繼承的解釋與處理詳解

    菱形繼承是多重繼承中跑不掉的,Java拿掉了多重繼承,輔之以接口。C++中雖然沒有明確說(shuō)明接口這種東西,但是只有純虛函數(shù)的類可以看作Java中的接口,下面這篇文章主要給大家介紹了關(guān)于C++中菱形繼承的解釋與處理的相關(guān)資料,需要的朋友可以參考下
    2022-02-02
  • C++冒泡排序與選擇排序詳解

    C++冒泡排序與選擇排序詳解

    大家好,本篇文章主要講的是C++冒泡排序與選擇排序詳解,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽
    2021-12-12

最新評(píng)論

张家港市| 威信县| 焉耆| 汉寿县| 茂名市| 保康县| 沂源县| 曲周县| 宁河县| 维西| 青河县| 仲巴县| 新津县| 宿松县| 平果县| 大方县| 科技| 江川县| 江华| 辽中县| 招远市| 嘉善县| 三门峡市| 临城县| 万源市| 庆安县| 福泉市| 乐亭县| 安义县| 清镇市| 易门县| 广安市| 龙山县| 运城市| 旅游| 永定县| 南康市| 台中县| 保靖县| 江达县| 罗江县|