真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

C++的new和delete的用法

本篇內(nèi)容介紹了“C++的new和delete的用法”的有關(guān)知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細閱讀,能夠?qū)W有所成!

創(chuàng)新互聯(lián)主要從事成都網(wǎng)站制作、成都做網(wǎng)站、外貿(mào)營銷網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)諸暨,10余年網(wǎng)站建設(shè)經(jīng)驗,價格優(yōu)惠、服務(wù)專業(yè),歡迎來電咨詢建站服務(wù):028-86922220

new和delete的內(nèi)部實現(xiàn)

C++中如果要在堆內(nèi)存中創(chuàng)建和銷毀對象需要借助關(guān)鍵字new和delete來完成。比如下面的代碼

class CA
{
 public:
  CA()m_a(0){}
  CA(int a):m_a(a){}
  virtual void foo(){ cout<

new和delete既是C++中的關(guān)鍵字也是一種特殊的運算符。

void* operator new(size_t size);
 void* operator new[](size_t size);
 void operator delete(void *p);
 void operator delete[](void *p);

new和delete不僅承載著內(nèi)存分配的功能還承載著對象構(gòu)造函數(shù)的調(diào)用功能,因此上面的對象創(chuàng)建代碼其實在編譯時會轉(zhuǎn)化為如下的實現(xiàn):    

CA *p1 = operator new(sizeof(CA)); //分配堆內(nèi)存
  CA::CA(p1); //調(diào)用構(gòu)造函數(shù)
  CA *p2 = operator new(sizeof(CA)); //分配堆內(nèi)存
  CA::CA(p2, 10); //調(diào)用構(gòu)造函數(shù)
  CA *p3 = operator new[](20 * sizeof(CA));
  CA *pt = p3;
  for (int i = 0; i < 20; i++)
  {
   CA::CA(pt);
   pt += 1;
  }
  CA::~CA(p1);
  operator delete(p1);
  CA::~CA(p2);
  operator delete(p2);
  CA *pt = p3;
  for (int i = 0; i < 20; i++)
  {
   CA::~CA(pt);
   pt += 1;
  }
  operator delete[](p3);

看到上面的代碼也許你會感到疑惑,怎么在編譯時怎么會在源代碼的基礎(chǔ)上插入這么多的代碼。這也是很多C程序員吐槽C++語言的原因:C++編譯器會偷偷插入很多未知的代碼或者對源代碼進行修改和處理,而這些插入和修改動作對于程序員來說是完全不可知的!

言歸正傳,我們還能從上面的代碼中看出new和delete操作其實是分別進行了2步操作:1.內(nèi)存的分配,2.構(gòu)造函數(shù)的調(diào)用;3.析構(gòu)函數(shù)的調(diào)用,4.內(nèi)存的銷毀。所以當(dāng)對象是從堆內(nèi)存分配時,構(gòu)造函數(shù)執(zhí)前內(nèi)存就已經(jīng)完成分配,同樣當(dāng)析構(gòu)函數(shù)執(zhí)行完成后內(nèi)存才會被銷毀。

這里面一個有意思的問題就是當(dāng)我們分配或者銷毀的是數(shù)組對象時,系統(tǒng)又是如何知道應(yīng)該調(diào)用多少次構(gòu)造函數(shù)以及調(diào)用多少次析構(gòu)函數(shù)的呢?答案就是在內(nèi)存分配里面。當(dāng)我們調(diào)用operator new[]來分配數(shù)組對象時,編譯器時系統(tǒng)內(nèi)部會增加4或者8字節(jié)的分配空間用來保存所分配的數(shù)組對象的數(shù)量。當(dāng)對數(shù)組對象調(diào)用構(gòu)造和析構(gòu)函數(shù)時就可以根據(jù)這個數(shù)量值來進行循環(huán)處理了。因此上面對數(shù)組對象的分配和銷毀的真實代碼其實是按如下方式處理的:

 // CA *p3 = new CA[20]; 這句代碼在編譯時其實會轉(zhuǎn)化為如下的代碼片段
  unsigned long *p = operator new[](20 * sizeof(CA) + sizeof(unsigned long)); //64位系統(tǒng)多分配8字節(jié)
  *p = 20; //這里保存分配的對象的數(shù)量。
  CA *p3 = (CA*)(p + 1);
  CA *pt = p3;
  for (int i = 0; i < *p; i++)
  {
   CA::CA(pt);
   pt += 1;
  }
 // delete[] p3; 這句代碼在編譯時其實會轉(zhuǎn)化為如下的代碼片段
  unsigned long *p = ((unsigned long*)p3) - 1;
  CA *pt = p3;
  for (int i = 0; i < *p; i++)
  {
   CA::~CA(pt);
   pt += 1;
  }
  operator delete[](p);

可見C++中為我們隱藏了多少細節(jié)??!既然new和delete操作默認是從堆中進行內(nèi)存分配,而且new和delete又是一個普通的運算符函數(shù),那么他內(nèi)部是如何實現(xiàn)呢?其實也很簡單。我們知道C語言中堆內(nèi)存分配和銷毀的函數(shù)是malloc/free。因此C++中對系統(tǒng)默認的new和delete運算符函數(shù)就可以按如下的方法實現(xiàn):

void * operator new(size_t size)
{
  return malloc(size);
} 
void * operator new[](size_t size)
{
  return malloc(size);
}
void operator delete(void *p)
{
  free(p);
}
void operator delete[](void *p)
{
 free(p);
}

這里需要注意的是你在代碼里面使用new關(guān)鍵字和使用operator new操作符所產(chǎn)生的效果是不一樣的。如果你在代碼里面使用的是new關(guān)鍵字那么系統(tǒng)內(nèi)部除了會調(diào)用operator new操作符來分配內(nèi)存還會調(diào)用構(gòu)造函數(shù),而如果你直接使用operator new時則只會進行內(nèi)存分配而不會執(zhí)行任何構(gòu)造就比如下面的代碼: 

 CA *p1 = new CA; //這里會分配內(nèi)存和執(zhí)行構(gòu)造函數(shù)
 CA *p2 = operator new(sizeof(CA)); //這里只是執(zhí)行了普通的堆內(nèi)存分配而不會調(diào)用構(gòu)造函數(shù)

上述的偽代碼都是在運行時通過查看匯編語言而得出的結(jié)論,我是在XCODE編譯器上查看運行的結(jié)果,有可能不同的編譯器會有一些實現(xiàn)的差異,但是不管如何要想真實的了解內(nèi)部實現(xiàn)原理還是要懂一些匯編的知識為最好。

placement技術(shù)

系統(tǒng)默認的new關(guān)鍵字除了分配堆內(nèi)存外還進行構(gòu)造函數(shù)的調(diào)用。而實際中我們可能有一些已經(jīng)預(yù)先分配好的內(nèi)存區(qū)域,我們想在這些已經(jīng)分配好的內(nèi)存中來構(gòu)建一個對象。還有一種情況是不希望進行頻繁的堆內(nèi)存分配和釋放而只是對同一塊內(nèi)存進行重復(fù)的對象構(gòu)建和銷毀。就如下面的代碼:

char buf1[100];
CA *p1 = (CA*)buf1;
CA::CA(p1);
p1->foo();
p1->m_a = 10;
char *buf2 = new char[sizeof(CA)];
CA *p2 = (CA*)buf2;
CA::CA(p2);
p2->foo();
p2->m_a = 20;
p1->~CA();
p2->~CA();
delete[] buf2;

可以看出代碼中buf1是棧內(nèi)存而buf2是堆內(nèi)存,這兩塊內(nèi)存區(qū)域都是已經(jīng)分配好了的內(nèi)存,現(xiàn)在我們想把這些內(nèi)存來當(dāng)做CA類的對象來使用,因此我們需要對內(nèi)存調(diào)用類的構(gòu)造函數(shù)CA::CA()才可以,構(gòu)造函數(shù)的內(nèi)部實現(xiàn)會為內(nèi)存區(qū)域填充虛表指針,這樣對象才可以調(diào)用諸如foo虛函數(shù)。但是這樣寫代碼不夠優(yōu)雅,那么有沒有比較優(yōu)雅的方法來實現(xiàn)在一塊已經(jīng)存在的內(nèi)存上來構(gòu)建對象呢? 答案就是 placement技術(shù)。 C++中的仍然是使用new和delete來實現(xiàn)這種技術(shù)。new和delete除了實現(xiàn)默認的操作符外還重載實現(xiàn)了如下的操作符函數(shù):

void* operator new(size_t size, void *p)
{
 return p;
}
void* operator new[](size_t size, void *p)
{
 return p;
}
void operator delete(void *p1, void *p2)
{
 // do nothing..
}
void operator delete[](void *p1, void *p2)
{
 // do nothing..
}

我們稱這四個運算符為 placement new 和 placement delete  。通過這幾個運算符我們就可以優(yōu)雅的實現(xiàn)上述的功能:

char buf1[100];
CA *p1 = new(buf1) CA(10); //調(diào)用 operator new(size_t, void*)
p1->foo();
char *buf2 = new char[sizeof(CA)];
CA *p2 = new(buf2) CA(20);  //調(diào)用 operator new(size_t, void*)
p2->foo();
p1->~CA();
operator delete(p1, buf1); //調(diào)用 operator delete(void*, void*)
p2->~CA();
operator delete(p2, buf2); //調(diào)用 operator delete(void*, void*)
delete[] buf2;

上面的例子里面發(fā)現(xiàn)通過placement new可以很優(yōu)雅的在現(xiàn)有的內(nèi)存中構(gòu)建對象,而析構(gòu)時不能直接調(diào)用delete p1, delete p2來銷毀對象,必須人為的調(diào)用析構(gòu)函數(shù)以及placement delete 函數(shù)。并且從上面的placement delete的實現(xiàn)來看里面并沒有任何代碼,既然如此為什么還要定義一個placement   delete呢? 答案就是C++中的規(guī)定對new和delete的運算符重載必須是要成對實現(xiàn)的。而且前面曾經(jīng)說過對delete的使用如果帶了operator前綴時就只是一個普通的函數(shù)調(diào)用。因此為了完成析構(gòu)以及和new操作符的匹配,就必須要人為的調(diào)用對象的析構(gòu)函數(shù)以及placement delete函數(shù)。
除了上面舉的例子外placement技術(shù)的使用還可以減少內(nèi)存的頻繁分配以及提升系統(tǒng)的性能。

void main()
{
  for (int i = 0; i < 10000; i++)
  {
   CA *p = new CA(i);
   p->foo();
   delete p;
  }
}

例子里面循環(huán)10000次,每次循環(huán)都創(chuàng)建一個堆內(nèi)存對象,然后調(diào)用虛函數(shù)foo后再進行銷毀。最終的結(jié)果是程序運行時會進行10000次的頻繁的堆內(nèi)存分配和銷毀。很明顯這是有可能會影響系統(tǒng)性能的而且還有可能發(fā)生堆內(nèi)存分配失敗的情況。而如果我們借助placement 技術(shù)就可以很簡單的解決這些問題。

void main()
{
  char *buf = new[](sizeof(CA));
  for (int i = 0; i < 10000; i++)
  {
   CA *p = new(buf) CA(i);
   p->foo();
   p->~CA();
   operator delete(p, buf);
  }
  delete[] buf;
}

上面的例子里面只進行了一次堆內(nèi)存分配,在循環(huán)里面都是借助已經(jīng)存在的內(nèi)存來構(gòu)建對象,不會再分配內(nèi)存了。這樣對內(nèi)存的重復(fù)利用就使得程序的性能得到非常大的提升。

new和delete運算符重載

發(fā)現(xiàn)一個很有意思的事情就是越高級的語言就越會將一些系統(tǒng)底層的東西進行封裝并形成一個語言級別的關(guān)鍵字來使用。比如C++中的new和delete是用于構(gòu)建和釋放堆內(nèi)存對象的關(guān)鍵字,又比如go語言中chan關(guān)鍵字是用于進行同步或者異步的隊列數(shù)據(jù)傳輸通道。

C++語言內(nèi)置默認實現(xiàn)了一套全局new和delete的運算符函數(shù)以及placement new/delete運算符函數(shù)。不管是類還是內(nèi)置類型都可以通過new/delete來進行堆內(nèi)存對象的分配和釋放的。對于一個類來說,當(dāng)我們使用new來進行構(gòu)建對象時,首先會檢查這個類是否重載了new運算符,如果這個類重載了new運算符那么就會調(diào)用類提供的new運算符來進行內(nèi)存分配,而如果沒有提供new運算符時就使用系統(tǒng)提供的全局new運算符來進行內(nèi)存分配。內(nèi)置類型則總是使用系統(tǒng)提供的全局new運算符來進行內(nèi)存的分配。對象的內(nèi)存銷毀流程也是和分配一致的。

new和delete運算符既支持全局的重載又支持類級別的函數(shù)重載。下面是這種運算符的定義的格式:

//全局運算符定義格式
void * operator new(size_t size [, param1, param2,....]);
void operator delete(void *p [, param1, param2, ...]);
//類內(nèi)運算符定義格式
class CA
{
 void * operator new(size_t size [, param1, param2,....]);
 void operator delete(void *p [, param1, param2, ...]);
};

對于new/delete運算符重載我們總有如何下規(guī)則:

new和delete運算符重載必須成對出現(xiàn)

new運算符的第一個參數(shù)必須是size_t類型的,也就是指定分配內(nèi)存的size尺寸;delete運算符的第一個參數(shù)必須是要銷毀釋放的內(nèi)存對象。其他參數(shù)可以任意定義。

系統(tǒng)默認實現(xiàn)了new/delete、new[]/delete[]、 placement new / delete 6個運算符函數(shù)。它們都有特定的意義。
你可以重寫默認實現(xiàn)的全局運算符,比如你想對內(nèi)存的分配策略進行自定義管理或者你想監(jiān)測堆內(nèi)存的分配情況或者你想做堆內(nèi)存的內(nèi)存泄露監(jiān)控等。但是你重寫的全局運算符一定要滿足默認的規(guī)則定義。

如果你想對某個類的堆內(nèi)存分配的對象做特殊處理,那么你可以重載這個類的new/delete運算符。當(dāng)重載這兩個運算符時雖然沒有帶static屬性,但是不管如何對類的new/delete運算符的重載總是被認為是靜態(tài)成員函數(shù)。

當(dāng)delete運算符的參數(shù)>=2個時,就需要自己負責(zé)對象析構(gòu)函數(shù)的調(diào)用,并且以運算符函數(shù)的形式來調(diào)用delete運算符。

一般情況下你不需要對new/delete運算符進行重載,除非你的整個應(yīng)用或者某個類有特殊的需求時才會如此。下面的例子你可以看到我的各種運算符的重載方法以及使用方法:

//CA.h
class CA
{
public:
 //類成員函數(shù)
 void * operator new(size_t size);
 void * operator new[](size_t size);
 void * operator new(size_t size, void *p);
 void * operator new(size_t size, int a, int b);
 void operator delete(void *p);
 void operator delete[](void *p);
 void operator delete(void *p, void *p1);
 void operator delete(void *p, int a, int b);
};
class CB
{
public:
 CB(){}
};
//全局運算符函數(shù),請謹慎重寫覆蓋全局運算符函數(shù)。
void * operator new(size_t size);
void * operator new[](size_t size);
void * operator new(size_t size, void *p) noexcept;
void * operator new(size_t size, int a, int b);
void operator delete(void *p);
void operator delete[](void *p);
void operator delete(void *p, void *p1);
void operator delete(void *p, int a, int b);
.......................................................
//CA.cpp
void * CA::operator new(size_t size)
{
 return malloc(size);
}
void * CA::operator new[](size_t size)
{
 return malloc(size);
}
void * CA::operator new(size_t size, void *p)
{
 return p;
}
void* CA::operator new(size_t size, int a, int b)
{
 return malloc(size);
}
void CA::operator delete(void *p)
{
 free(p);
}
void CA::operator delete[](void *p)
{
 free(p);
}
void CA::operator delete(void *p, void *p1)
{
}
void CA::operator delete(void *p, int a, int b)
{
 free(p);
}
void * operator new(size_t size)
{
 return malloc(size);
}
void * operator new[](size_t size)
{
 return malloc(size);
}
void * operator new(size_t size, void *p) noexcept
{
 return p;
}
void* operator new(size_t size, int a, int b)
{
 return malloc(size);
}
void operator delete(void *p)
{
 free(p);
}
void operator delete[](void *p)
{
 free(p);
}
void operator delete(void *p, void *p1)
{
}
void operator delete(void *p, int a, int b)
{
 free(p);
}
..................................
//main.cpp
int main(int argc, const char * argv[]) {
 char buf[100];
 CA *a1 = new CA(); //調(diào)用void * CA::operator new(size_t size)
 CA *a2 = new CA[10]; //調(diào)用void * CA::operator new[](size_t size)
 CA *a3 = new(buf)CA(); //調(diào)用void * CA::operator new(size_t size, void *p)
 CA *a4 = new(10, 20)CA(); //調(diào)用void* CA::operator new(size_t size, int a, int b)
 delete a1; //調(diào)用void CA::operator delete(void *p)
 delete[] a2; //調(diào)用void CA::operator delete[](void *p)
 //a3用的是placement new的方式分配,因此需要自己調(diào)用對象的析構(gòu)函數(shù)。
 a3->~CA();
 CA::operator delete(a3, buf); //調(diào)用void CA::operator delete(void *p, void *p1),記得要帶上類命名空間。
 //a4的運算符參數(shù)大于等于2個所以需要自己調(diào)用對象的析構(gòu)函數(shù)。
 a4->~CA();
 CA::operator delete(a4, 10, 20); //調(diào)用void CA::operator delete(void *p, int a, int b)
 //CB類沒有重載運算符,因此使用的是全局重載的運算符。
 CB *b1 = new CB(); //調(diào)用void * operator new(size_t size)
 CB *b2 = new CB[10]; //調(diào)用void * operator new[](size_t size)
 //這里你可以看到同一塊內(nèi)存可以用來構(gòu)建CA類的對象也可以用來構(gòu)建CB類的對象
 CB *b3 = new(buf)CB(); //調(diào)用void * operator new(size_t size, void *p)
 CB *b4 = new(10, 20)CB(); //調(diào)用void* operator new(size_t size, int a, int b)
 delete b1; //調(diào)用void operator delete(void *p)
 delete[] b2; //調(diào)用void operator delete[](void *p)
 //b3用的是placement new的方式分配,因此需要自己調(diào)用對象的析構(gòu)函數(shù)。
 b3->~CB();
 ::operator delete(b3, buf); //調(diào)用void operator delete(void *p, void *p1)
 //b4的運算符參數(shù)大于等于2個所以需要自己調(diào)用對象的析構(gòu)函數(shù)。
 b4->~CB();
 ::operator delete(b4, 10, 20); //調(diào)用void operator delete(void *p, int a, int b)
 return 0;
}

我是在XCODE上測試上面的代碼的,因為重寫了全局的new/delete運算符,并且內(nèi)部是通過malloc來實現(xiàn)堆內(nèi)存分配的, malloc函數(shù)申明了不能返回NULL的返回結(jié)果檢測:

void *malloc(size_t __size) __result_use_check __alloc_size(1);

因此有可能你在測試時會發(fā)生崩潰的問題。如果出現(xiàn)這個問題你可以嘗試著注釋掉對全局new/delete重寫的代碼,再運行查看結(jié)果。 可見如果你嘗試著覆蓋重寫全局的new/delete時是有可能產(chǎn)生風(fēng)險的。

對象的自動刪除技術(shù)

一般來說系統(tǒng)對new/delete的默認實現(xiàn)就能滿足我們的需求,我們不需要再去重載這兩個運算符。那為什么C++還提供對這兩個運算符的重載支持呢?答案還是在運算符本身具有的缺陷所致。我們知道用new關(guān)鍵字來創(chuàng)建堆內(nèi)存對象是分為了2步:1.是堆內(nèi)存分配,2.是對象構(gòu)造函數(shù)的調(diào)用。而這兩步中的任何一步都有可能會產(chǎn)生異常。如果說是在第一步出現(xiàn)了問題導(dǎo)致內(nèi)存分配失敗則不會調(diào)用構(gòu)造函數(shù),這是沒有問題的。如果說是在第二步構(gòu)造函數(shù)執(zhí)行過程中出現(xiàn)了異常而導(dǎo)致無法正常構(gòu)造完成,那么就應(yīng)該要將第一步中所分配的堆內(nèi)存進行銷毀。C++中規(guī)定如果一個對象無法完全構(gòu)造那么這個對象將是一個無效對象,也不會調(diào)用析構(gòu)函數(shù)。為了保證對象的完整性,當(dāng)通過new分配的堆內(nèi)存對象在構(gòu)造函數(shù)執(zhí)行過程中出現(xiàn)異常時就會停止構(gòu)造函數(shù)的執(zhí)行并且自動調(diào)用對應(yīng)的delete運算符來對已經(jīng)分配的堆內(nèi)存執(zhí)行銷毀處理,這就是所謂的對象的自動刪除技術(shù)。正是因為有了對象的自動刪除技術(shù)才能解決對象構(gòu)造不完整時會造成內(nèi)存泄露的問題。

當(dāng)對象構(gòu)造過程中拋出異常時,C++的異常處理機制會在特定的地方插入代碼來實現(xiàn)對對象的delete運算符的調(diào)用,如果想要具體了解情況請參考C++對異常處理實現(xiàn)的相關(guān)知識點。

全局delete運算符函數(shù)所支持的對象的自動刪除技術(shù)雖然能解決對象本身的內(nèi)存泄露問題,但是卻不能解決對象構(gòu)造函數(shù)內(nèi)部的數(shù)據(jù)成員的內(nèi)存分配泄露問題,我們來看下面的代碼:

class CA
{
 public:
 CA()
 {
   m_pa = new int;
   throw 1;
 }
 ~CA()
 {
   delete m_pa;
   m_pa = NULL;
 }
 private:
  int *m_pa;
};
void main()
{
  try
  {
   CA *p = new CA();
   delete p; //這句代碼永遠不會執(zhí)行
  }
  catch(int)
 {
   cout << "oops!" << endl;
 }
}

上面的代碼中可以看到類CA中的對象在構(gòu)造函數(shù)內(nèi)部拋出了異常,雖然系統(tǒng)會對p對象執(zhí)行自動刪除技術(shù)來銷毀分配好的內(nèi)存,但是對于其內(nèi)部的數(shù)據(jù)成員m_pa來說,因為構(gòu)造不完整就不會調(diào)用析構(gòu)函數(shù)來銷毀分配的堆內(nèi)存,這樣就導(dǎo)致了m_pa這塊內(nèi)存出現(xiàn)了泄露。怎么解決這類問題呢? 答案你是否想到了? 那就是重載CA類的new/delete運算符。我們來看通過對CA重載運算符解決問題的代碼:

class CA
{
public:
 CA(){
  m_pa = new int;
  throw 1;
 }
 //因為對象構(gòu)造未完成所以析構(gòu)函數(shù)永遠不會被調(diào)用
 ~CA()
 {
  delete m_pa;
  m_pa = NULL;
 }
 void * operator new(size_t size)
 {
  return malloc(size);
 }
 //重載delete運算符,把已經(jīng)分配的內(nèi)存銷毀掉。
 void operator delete(void *p)
 {
  CA *pb = (CA*)p;
  if (pb->m_pa != NULL)
   delete pb->m_pa;
  free(p);
 }
private:
 int *m_pa;
};

因為C++對自動刪除技術(shù)的支持,當(dāng)CA對象在構(gòu)造過程中發(fā)生異常時,我們就可以通過重載delete運算符來解決那些在構(gòu)造函數(shù)中分配的數(shù)據(jù)成員內(nèi)存但又不會調(diào)用析構(gòu)函數(shù)來銷毀的數(shù)據(jù)成員的內(nèi)存問題。這我想就是為什么C++中要支持對new/delete運算符在類中重載的原因吧。

下面看下:new和delete使用注意事項

1. new 和delete都是內(nèi)建的操作符,語言本身所固定了,無法重新定制,想要定制new和delete的行為,徒勞無功的行為。

2. 動態(tài)分配失敗,則返回一個空指針(NULL),表示發(fā)生了異常,堆資源不足,分配失敗。

3. 指針刪除與堆空間釋放。刪除一個指針p(delete p;)實際意思是刪除了p所指的目標(變量或?qū)ο蟮龋?,釋放了它所占的堆空間,而不是刪除p本身(指針p本身并沒有撤銷,它自己仍然存在,該指針所占內(nèi)存空間并未釋放),釋放堆空間后,p成了空指針。

4. 內(nèi)存泄漏(memory leak)和重復(fù)釋放。new與delete 是配對使用的, delete只能釋放堆空間。如果new返回的指針值丟失,則所分配的堆空間無法回收,稱內(nèi)存泄漏,同一空間重復(fù)釋放也是危險的,因為該空間可能已另分配,所以必須妥善保存new返回的指針,以保證不發(fā)生內(nèi)存泄漏,也必須保證不會重復(fù)釋放堆內(nèi)存空間。

5. 動態(tài)分配的變量或?qū)ο蟮纳凇N覀円卜Q堆空間為自由空間(free store),但必須記住釋放該對象所占堆空間,并只能釋放一次,在函數(shù)內(nèi)建立,而在函數(shù)外釋放,往往會出錯。

6. 要訪問new所開辟的結(jié)構(gòu)體空間,無法直接通過變量名進行,只能通過賦值的指針進行訪問。

    用new和delete可以動態(tài)開辟和撤銷地址空間。在編程序時,若用完一個變量(一般是暫時存儲的數(shù)據(jù)),下次需要再用,但卻又想省去重新初始化的功夫,可以在每次開始使用時開辟一個空間,在用完后撤銷它。

“C++的new和delete的用法”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實用文章!


文章名稱:C++的new和delete的用法
標題路徑:http://weahome.cn/article/gphpjs.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部