精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

看完這篇你還能不懂C語言/C++內存管理?

開發 后端 存儲軟件
C 語言內存管理指對系統內存的分配、創建、使用這一系列操作。在內存管理中,由于是操作系統內存,使用不當會造成畢竟麻煩的結果。本文將從系統內存的分配、創建出發,并且使用例子來舉例說明內存管理不當會出現的情況及解決辦法。

 C 語言內存管理指對系統內存的分配、創建、使用這一系列操作。在內存管理中,由于是操作系統內存,使用不當會造成畢竟麻煩的結果。本文將從系統內存的分配、創建出發,并且使用例子來舉例說明內存管理不當會出現的情況及解決辦法。

[[350266]]

一、內存

在計算機中,每個應用程序之間的內存是相互獨立的,通常情況下應用程序 A 并不能訪問應用程序 B,當然一些特殊技巧可以訪問,但此文并不詳細進行說明。例如在計算機中,一個視頻播放程序與一個瀏覽器程序,它們的內存并不能訪問,每個程序所擁有的內存是分區進行管理的。

在計算機系統中,運行程序 A 將會在內存中開辟程序 A 的內存區域 1,運行程序 B 將會在內存中開辟程序 B 的內存區域 2,內存區域 1 與內存區域 2 之間邏輯分隔。

1.1 內存四區

在程序 A 開辟的內存區域 1 會被分為幾個區域,這就是內存四區,內存四區分為棧區、堆區、數據區與代碼區。

棧區指的是存儲一些臨時變量的區域,臨時變量包括了局部變量、返回值、參數、返回地址等,當這些變量超出了當前作用域時將會自動彈出。該棧的最大存儲是有大小的,該值固定,超過該大小將會造成棧溢出。

堆區指的是一個比較大的內存空間,主要用于對動態內存的分配;在程序開發中一般是開發人員進行分配與釋放,若在程序結束時都未釋放,系統將會自動進行回收。

數據區指的是主要存放全局變量、常量和靜態變量的區域,數據區又可以進行劃分,分為全局區與靜態區。全局變量與靜態變量將會存放至該區域。

代碼區就比較好理解了,主要是存儲可執行代碼,該區域的屬性是只讀的。

1.2 使用代碼證實內存四區的底層結構

由于棧區與堆區的底層結構比較直觀的表現,在此使用代碼只演示這兩個概念。首先查看代碼觀察棧區的內存地址分配情況:

  1. #include<stdio.h> 
  2. int main() 
  3.  int a = 0; 
  4.  int b = 0; 
  5.  char c='0'
  6.  printf("變量a的地址是:%d\n變量b的地址是:%d\n變量c的地址是:%d\n", &a, &b, &c); 
  7.  

運行結果為:

我們可以觀察到變量 a 的地址是 2293324 變量 b 的地址是 2293320,由于 int 的數據大小為 4 所以兩者之間間隔為 4;再查看變量 c,我們發現變量 c 的地址為 2293319,與變量 b 的地址 2293324 間隔 1,因為 c 的數據類型為 char,類型大小為 1。在此我們觀察發現,明明我創建變量的時候順序是 a 到 b 再到 c,為什么它們之間的地址不是增加而是減少呢?那是因為棧區的一種數據存儲結構為先進后出,如圖:

首先棧的頂部為地址的“最小”索引,隨后往下依次增大,但是由于堆棧的特殊存儲結構,我們將變量 a 先進行存儲,那么它的一個索引地址將會是最大的,隨后依次減少;第二次存儲的值是 b,該值的地址索引比 a 小,由于 int 的數據大小為 4,所以在 a 地址為 2293324 的基礎上往上減少 4 為 2293320,在存儲 c 的時候為 char,大小為 1,則地址為 2293319。由于 a、b、c 三個變量同屬于一個棧內,所以它們地址的索引是連續性的,那如果我創建一個靜態變量將會如何?在以上內容中說明了靜態變量存儲在靜態區內,我們現在就來證實一下:

  1. #include<stdio.h> 
  2. int main() 
  3.   
  4.  int a = 0; 
  5.  int b = 0; 
  6.  char c='0'
  7.  static int d = 0; 
  8.   
  9.  printf("變量a的地址是:%d\n變量b的地址是:%d\n變量c的地址是:%d\n", &a, &b, &c); 
  10.   
  11.  printf("靜態變量d的地址是:%d\n", &d); 
  12.  

運行結果如下:

以上代碼中創建了一個變量 d,變量 d 為靜態變量,運行代碼后從結果上得知,靜態變量 d 的地址與一般變量 a、b、c 的地址并不存在連續,他們兩個的內存地址是分開的。那接下來在此建一個全局變量,通過上述內容得知,全局變量與靜態變量都應該存儲在靜態區,代碼如下:

  1. #include<stdio.h> 
  2. int e = 0; 
  3. int main() 
  4.   
  5.  int a = 0; 
  6.  int b = 0; 
  7.  char c='0'
  8.  static int d = 0; 
  9.   
  10.  printf("變量a的地址是:%d\n變量b的地址是:%d\n變量c的地址是:%d\n", &a, &b, &c); 
  11.   
  12.  printf("靜態變量d的地址是:%d\n", &d); 
  13.  printf("全局變量e的地址是:%d\n", &e); 
  14.  

運行結果如下:

從以上運行結果中證實了上述內容的真實性,并且也得到了一個知識點,棧區、數據區都是使用棧結構對數據進行存儲。

在以上內容中還說明了一點棧的特性,就是容量具有固定大小,超過最大容量將會造成棧溢出。查看如下代碼:

  1. #include<stdio.h> 
  2.  
  3. int main() 
  4.  char arr_char[1024*1000000]; 
  5.     arr_char[0] = '0'

以上代碼定義了一個字符數組 arr_char,并且設置了大小為 1024*1000000,設置該數據是方便查看大小;隨后在數組頭部進行賦值。運行結果如下:

這是程序運行出錯,原因是造成了棧的溢出。在平常開發中若需要大容量的內存,需要使用堆。

堆并沒有棧一樣的結構,也沒有棧一樣的先進后出。需要人為的對內存進行分配使用。代碼如下:

  1. #include<stdio.h> 
  2. #include<string.h> 
  3. #include <malloc.h> 
  4. int main() 
  5.  char *p1 = (char *)malloc(1024*1000000); 
  6.  strcpy(p1, "這里是堆區"); 
  7.  printf("%s\n", p1); 

以上代碼中使用了strcpy 往手動開辟的內存空間 p1 中傳數據“這里是堆區”,手動開辟空間使用 malloc,傳入申請開辟的空間大小 1024*1000000,在棧中那么大的空間必定會造成棧溢出,而堆本身就是大容量,則不會出現該情況。隨后輸出開辟的內存中內容,運行結果如下:

在此要注意p1是表示開辟的內存空間地址。

二、malloc 和 free

在 C 語言(不是 C++)中,malloc 和 free 是系統提供的函數,成對使用,用于從堆中分配和釋放內存。malloc 的全稱是 memory allocation 譯為“動態內存分配”。

2.1 malloc 和 free 的使用

在開辟堆空間時我們使用的函數為 malloc,malloc 在 C 語言中是用于申請內存空間,malloc 函數的原型如下:

  1. void *malloc(size_t size); 

在 malloc 函數中,size 是表示需要申請的內存空間大小,申請成功將會返回該內存空間的地址;申請失敗則會返回 NULL,并且申請成功也不會自動進行初始化。

細心的同學可能會發現,該函數的返回值說明為 void *,在這里 void * 并不指代某一種特定的類型,而是說明該類型不確定,通過接收的指針變量從而進行類型的轉換。在分配內存時需要注意,即時在程序關閉時系統會自動回收該手動申請的內存 ,但也要進行手動的釋放,保證內存能夠在不需要時返回至堆空間,使內存能夠合理的分配使用。

釋放空間使用 free 函數,函數原型如下:

  1. void free(void *ptr); 

free 函數的返回值為 void,沒有返回值,接收的參數為使用 malloc 分配的內存空間指針。一個完整的堆內存申請與釋放的例子如下:

  1. #include<stdio.h> 
  2. #include<string.h> 
  3. #include <malloc.h> 
  4.  
  5. int main() { 
  6.     int n, *p, i; 
  7.     printf("請輸入一個任意長度的數字來分配空間:"); 
  8.     scanf("%d", &n); 
  9.      
  10.     p = (int *)malloc(n * sizeof(int)); 
  11.  if(p==NULL){ 
  12.   printf("申請失敗\n"); 
  13.   return 0; 
  14.  }else
  15.   printf("申請成功\n"); 
  16.  }  
  17.   
  18.  memset(p, 0, n * sizeof(int));//填充0  
  19.   
  20.  //查看  
  21.     for (i = 0; i < n; i++) 
  22.         printf("%d ", p[i]); 
  23.     printf("\n"); 
  24.  
  25.     free(p); 
  26.     p = NULL
  27.     return 0; 

以上代碼中使用了 malloc 創建了一個由用戶輸入創建指定大小的內存,判斷了內存地址是否創建成功,且使用了 memset 函數對該內存空間進行了填充值,隨后使用 for 循環進行了查看。最后使用了 free 釋放了內存,并且將 p 賦值 NULL,這點需要主要,不能使指針指向未知的地址,要置于 NULL;否則在之后的開發者會誤以為是個正常的指針,就有可能再通過指針去訪問一些操作,但是在這時該指針已經無用,指向的內存也不知此時被如何使用,這時若出現意外將會造成無法預估的后果,甚至導致系統崩潰,在 malloc 的使用中更需要需要。

2.2 內存泄漏與安全使用實例與講解

內存泄漏是指在動態分配的內存中,并沒有釋放內存或者一些原因造成了內存無法釋放,輕度則造成系統的內存資源浪費,嚴重的導致整個系統崩潰等情況的發生。

[[350273]]

內存泄漏通常比較隱蔽,且少量的內存泄漏發生不一定會發生無法承受的后果,但由于該錯誤的積累將會造成整體系統的性能下降或系統崩潰。特別是在較為大型的系統中,如何有效的防止內存泄漏等問題的出現變得尤為重要。例如一些長時間的程序,若在運行之初有少量的內存泄漏的問題產生可能并未呈現,但隨著運行時間的增長、系統業務處理的增加將會累積出現內存泄漏這種情況;這時極大的會造成不可預知的后果,如整個系統的崩潰,造成的損失將會難以承受。由此防止內存泄漏對于底層開發人員來說尤為重要。

C 程序員在開發過程中,不可避免的面對內存操作的問題,特別是頻繁的申請動態內存時會及其容易造成內存泄漏事故的發生。如申請了一塊內存空間后,未初始化便讀其中的內容、間接申請動態內存但并沒有進行釋放、釋放完一塊動態申請的內存后繼續引用該內存內容;如上所述這種問題都是出現內存泄漏的原因,往往這些原因由于過于隱蔽在測試時不一定會完全清楚,將會導致在項目上線后的長時間運行下,導致災難性的后果發生。

如下是一個在子函數中進行了內存空間的申請,但是并未對其進行釋放:

  1. #include<stdio.h> 
  2. #include<string.h> 
  3. #include <malloc.h> 
  4. void m() {  
  5.  char *p1;  
  6.  p1 = malloc(100);  
  7.  printf("開始對內存進行泄漏..."); 
  8.   
  9. int main() { 
  10.     m(); 
  11.     return 0; 

如上代碼中,使用 malloc 申請了 100 個單位的內存空間后,并沒有進行釋放。假設該 m 函數在當前系統中調用頻繁,那將會每次使用都將會造成 100 個單位的內存空間不會釋放,久而久之就會造成嚴重的后果。理應在 p1 使用完畢后添加 free 進行釋放:

  1. free(p1); 

以下示范一個讀取文件時不規范的操作:

  1. #include<stdio.h> 
  2. #include<string.h> 
  3. #include <malloc.h> 
  4. int m(char *filename) {  
  5.  FILE* f; 
  6.  int key;  
  7.  f = fopen(filename, "r");  
  8.  fscanf(f, "%d", &key);  
  9.  return key;  
  10.   
  11. int main() { 
  12.     m("number.txt"); 
  13.     return 0; 

以上文件在讀取時并沒有進行 fclose,這時將會產生多余的內存,可能一次還好,多次會增加成倍的內存,可以使用循環進行調用,之后在任務管理器中可查看該程序運行時所占的內存大小,代碼為:

  1. #include<stdio.h> 
  2. #include<string.h> 
  3. #include <malloc.h> 
  4. int m(char *filename) {  
  5.  FILE* f; 
  6.  int key;  
  7.  f = fopen(filename, "r");  
  8.  fscanf(f, "%d", &key);  
  9.  return key;  
  10.   
  11. int main() { 
  12.  int i; 
  13.  for(i=0;i<500;i++) { 
  14.      m("number.txt"); 
  15.  } 
  16.     return 0; 

可查看添加循環后的程序與添加循環前的程序做內存占用的對比,就可以發現兩者之間添加了循環的代碼將會成本增加占用容量。

未被初始化的指針也會有可能造成內存泄漏的情況,因為指針未初始化所指向不可控,如:

  1. int *p; 
  2. *p = val; 

包括錯誤的釋放內存空間:

  1. pp=p; 
  2. free(p);  
  3. free(pp); 

釋放后使用,產生懸空指針。在申請了動態內存后,使用指針指向了該內存,使用完畢后我們通過 free 函數釋放了申請的內存,該內存將會允許其它程序進行申請;但是我們使用過后的動態內存指針依舊指向著該地址,假設其它程序下一秒申請了該區域內的內存地址,并且進行了操作。當我依舊使用已 free 釋放后的指針進行下一步的操作時,或者所進行了一個計算,那么將會造成的結果天差地別,或者是其它災難性后果。所以對于這些指針在生存期結束之后也要置為 null。查看一個示例,由于 free 釋放后依舊使用該指針,造成的計算結果天差地別:

  1. #include<stdio.h> 
  2. #include<string.h> 
  3. #include <malloc.h> 
  4. int m(char *freep) {  
  5.  int val=freep[0]; 
  6.  printf("2*freep=:%d\n",val*2); 
  7.  free(freep); 
  8.  val=freep[0]; 
  9.  printf("2*freep=:%d\n",val*2); 
  10.   
  11. int main() { 
  12.  int *freep = (int *) malloc(sizeof (int)); 
  13.  freep[0]=1; 
  14.  m(freep); 
  15.     return 0; 
  16.      

以上代碼使用 malloc 申請了一個內存后,傳值為 1;在函數中首先使用 val 值接收 freep 的值,將 val 乘 2,之后釋放 free,重新賦值給 val,最后使用 val 再次乘 2,此時造成的結果出現了極大的改變,而且最恐怖的是該錯誤很難發現,隱蔽性很強,但是造成的后顧難以承受。運行結果如下:

三、 new 和 delete

C++ 中使用 new 和 delete 從堆中分配和釋放內存,new 和 delete 是運算符,不是函數,兩者成對使用(后面說明為什么成對使用)。

new/delete 除了分配內存和釋放內存(與 malloc/free),還做更多的事情,所有在 C++ 中不再使用 malloc/free 而使用 new/delete。

3.1 new 和 delete 使用

new 一般使用格式如下:

  • 指針變量名 = new 類型標識符;
  • 指針變量名 = new 類型標識符(初始值);
  • 指針變量名 = new 類型標識符[內存單元個數];

在C++中new的三種用法包括:plain new, nothrow new 和 placement new。

plain new 就是我們最常使用的 new 的方式,在 C++ 中的定義如下:

  1. void* operator new(std::size_t) throw(std::bad_alloc);   
  2. void operator delete( void *) throw(); 

plain new 在分配失敗的情況下,拋出異常 std::bad_alloc 而不是返回 NULL,因此通過判斷返回值是否為 NULL 是徒勞的。

  1. char *getMemory(unsigned long size)    
  2. {     
  3.     char * p = new char[size];    
  4.     return p;  
  5. }    
  6. void main(void)    
  7.     try{    
  8.         char * p = getMemory(1000000);    // 可能發生異常 
  9.         // ...    
  10.         delete [] p;    
  11.     }    
  12.     catch(const std::bad_alloc &amp; ex)    
  13.     { 
  14.         cout &lt;&lt; ex.what(); 
  15.     }    

nothrow new 是不拋出異常的運算符new的形式。nothrow new在失敗時,返回NULL。定義如下:

  1. void * operator new(std::size_t, const std::nothrow_t&) throw(); 
  2. void operator delete(void*) throw(); 
  1. void func(unsinged long length)    
  2.     unsinged char * p = new(nothrow) unsinged char[length];    
  3.     // 在使用這種new時要加(nothrow) ,表示不使用異常處理 。 
  4.   
  5.     if (p == NULL)  // 不拋異常,一定要檢查 
  6.         cout << "allocte failed !";    
  7.         // ...    
  8.     delete [] p; 

placement new 意即“放置”,這種new允許在一塊已經分配成功的內存上重新構造對象或對象數組。placement new不用擔心內存分配失敗,因為它根本不分配內存,它做的唯一一件事情就是調用對象的構造函數。定義如下:

  1. void* operator new(size_t, void*); 
  2. void operator delete(void*, void*); 

palcement new 的主要用途就是反復使用一塊較大的動態分配的內存來構造不同類型的對象或者他們的數組。placement new構造起來的對象或其數組,要顯示的調用他們的析構函數來銷毀,千萬不要使用delete。

  1. void main()    
  2. {   
  3.     using namespace std;    
  4.     char * p = new(nothrow) char [4];    
  5.     if (p == NULL)    
  6.     { 
  7.         cout << "allocte failed" << endl;   
  8.         exit( -1 ); 
  9.     }    
  10.     // ...    
  11.     long * q = new (p) long(1000);    
  12.     delete []p;    // 只釋放 p,不要用q釋放。 

p 和 q 僅僅是首址相同,所構建的對象可以類型不同。所“放置”的空間應小于原空間,以防不測。當”放置new”超過了申請的范圍,Debug 版下會崩潰,但 Release 能運行而不會出現崩潰!

該運算符的作用是:只要第一次分配成功,不再擔心分配失敗。

  1. void main()    
  2.     using namespace std;    
  3.     char * p = new(nothrow) char [100];    
  4.     if (p == NULL)    
  5.     {   
  6.         cout << "allocte failed" << endl; 
  7.         exit(-1); 
  8.     }    
  9.     long * q1 = new (p) long(100);    
  10.     // 使用q1  ...    
  11.     int * q2 = new (p) int[100/sizeof(int)];    
  12.     // 使用q2 ...    
  13.     ADT * q3 = new (p) ADT[100/sizeof(ADT)];    
  14.     // 使用q3  然后釋放對象 ...    
  15.     delete [] p;    // 只釋放空間,不再析構對象。 

注意:使用該運算符構造的對象或數組,一定要顯式調用析構函數,不可用 delete 代替析構,因為 placement new 的對象的大小不再與原空間相同。

  1. void main()    
  2. {   
  3.     using namespace std;    
  4.     char * p = new(nothrow) char [sizeof(ADT)+2];    
  5.     if (p == NULL)    
  6.     {   
  7.         cout << "allocte failed" &lt;&lt; endl; 
  8.         exit(-1);  
  9.     }  
  10.     // ...  
  11.     ADT * q = new (p) ADT;  
  12.     // ...  
  13.     // delete q; // 錯誤 
  14.     q->ADT::~ADT();  // 顯式調用析構函數,僅釋放對象 
  15.     delete [] p;     // 最后,再用原指針來釋放內存 

placement new 的主要用途就是可以反復使用一塊已申請成功的內存空間。這樣可以避免申請失敗的徒勞,又可以避免使用后的釋放。

特別要注意的是對于 placement new 絕不可以調用的 delete, 因為該 new 只是使用別人替它申請的地方。釋放內存是 nothrow new 的事,即要使用原來的指針釋放內存。free/delete 不要重復調用,被系統立即回收后再利用,再一次 free/delete 很可能把不是自己的內存釋放掉,導致異常甚至崩潰。

上面提到 new/delete 比 malloc/free 多做了一些事情,new 相對于 malloc 會額外的做一些初始化工作,delete 相對于 free 多做一些清理工作。

  1. class A 
  2.  public
  3.      A() 
  4.      { 
  5.         cont<<"A()構造函數被調用"<<endl; 
  6.      } 
  7.      ~A() 
  8.      { 
  9.         cont<<"~A()構造函數被調用"<<endl; 
  10.      } 

在 main 主函數中,加入如下代碼:

  1. A* pa = new A();  //類 A 的構造函數被調用 
  2. delete pa;        //類 A 的析構函數被調用 

可以看出:使用 new 生成一個類對象時系統會調用該類的構造函數,使用 delete 刪除一個類對象時,系統會調用該類的析構函數??梢哉{用構造函數/析構函數就意味著 new 和 delete 具備針對堆所分配的內存進行初始化和釋放的能力,而 malloc 和 free 不具備。

2.2 delete 與 delete[] 的區別

c++ 中對 new 申請的內存的釋放方式有 delete 和 delete[] 兩種方式,到底這兩者有什么區別呢?

我們通常從教科書上看到這樣的說明:

  • delete 釋放 new 分配的單個對象指針指向的內存
  • delete[] 釋放 new 分配的對象數組指針指向的內存 那么,按照教科書的理解,我們看下下面的代碼:
  1. int *a = new int[10]; 
  2. delete a;        //方式1 
  3. delete[] a;     //方式2 

針對簡單類型 使用 new 分配后的不管是數組還是非數組形式內存空間用兩種方式均可 如:

  1. int *a = new int[10]; 
  2. delete a; 
  3. delete[] a; 

此種情況中的釋放效果相同,原因在于:分配簡單類型內存時,內存大小已經確定,系統可以記憶并且進行管理,在析構時,系統并不會調用析構函數。

它直接通過指針可以獲取實際分配的內存空間,哪怕是一個數組內存空間(在分配過程中 系統會記錄分配內存的大小等信息,此信息保存在結構體 _CrtMemBlockHeader 中,具體情況可參看 VC 安裝目錄下 CRTSRCDBGDEL.cpp)。

針對類 Class,兩種方式體現出具體差異

當你通過下列方式分配一個類對象數組:

  1. class A 
  2.    { 
  3.     private: 
  4.       char *m_cBuffer; 
  5.       int m_nLen; 
  6.  
  7.    `` public
  8.       A(){ m_cBuffer = new char[m_nLen]; } 
  9.       ~A() { delete [] m_cBuffer; } 
  10.    }; 
  11.  
  12.    A *a = new A[10]; 
  13.    delete a;         //僅釋放了a指針指向的全部內存空間 但是只調用了a[0]對象的析構函數 剩下的從a[1]到a[9]這9個用戶自行分配的m_cBuffer對應內存空間將不能釋放 從而造成內存泄漏 
  14.    delete[] a;      //調用使用類對象的析構函數釋放用戶自己分配內存空間并且   釋放了a指針指向的全部內存空間 

所以總結下就是,如果 ptr 代表一個用new申請的內存返回的內存空間地址,即所謂的指針,那么:

delete ptr 代表用來釋放內存,且只用來釋放 ptr 指向的內存。delete[] rg 用來釋放rg指向的內存,!!還逐一調用數組中每個對象的destructor!!

對于像 int/char/long/int*/struct 等等簡單數據類型,由于對象沒有 destructor ,所以用 delete 和 delete []是一樣的!但是如果是 C++ 對象數組就不同了!

關于 new[] 和 delete[],其中又分為兩種情況:

(1) 為基本數據類型分配和回收空間;

(2) 為自定義類型分配和回收空間;

對于 (1),上面提供的程序已經證明了 delete[] 和 delete 是等同的。但是對于 (2),情況就發生了變化。

我們來看下面的例子,通過例子的學習了解 C++ 中的 delete 和 delete[] 的使用方法

  1. #include <iostream> 
  2. using namespace std; 
  3.  
  4. class Babe 
  5. public
  6.     Babe() 
  7.     { 
  8.         cout << \"Create a Babe to talk with me\" << endl; 
  9.     } 
  10.  
  11.     ~Babe() 
  12.     { 
  13.         cout << \"Babe don\'t Go away,listen to me\" << endl; 
  14.     } 
  15. }; 
  16.  
  17. int main() 
  18.     Babe* pbabe = new Babe[3]; 
  19.     delete pbabe; 
  20.     pbabe = new Babe[3]; 
  21.     delete[] pbabe; 
  22.     return 0; 

結果是:

  1. Create a babe to talk with me 
  2. Create a babe to talk with me 
  3. Create a babe to talk with me 
  4. Babe don\'t go away,listen to me 
  5. Create a babe to talk with me 
  6. Create a babe to talk with me 
  7. Create a babe to talk with me 
  8. Babe don\'t go away,listen to me 
  9. Babe don\'t go away,listen to me 
  10. Babe don\'t go away,listen to me 

大家都看到了,只使用 delete 的時候只出現一個 Babe don’t go away,listen to me,而使用 delete[] 的時候出現 3 個 Babe don’t go away,listen to me。不過不管使用 delete 還是 delete[] 那三個對象的在內存中都被刪除,既存儲位置都標記為可寫,但是使用 delete 的時候只調用了 pbabe[0] 的析構函數,而使用了 delete[] 則調用了 3 個 Babe 對象的析構函數。

你一定會問,反正不管怎樣都是把存儲空間釋放了,有什么區別。

答:關鍵在于調用析構函數上。此程序的類沒有使用操作系統的系統資源(比如:Socket、File、Thread等),所以不會造成明顯惡果。如果你的類使用了操作系統資源,單純把類的對象從內存中刪除是不妥當的,因為沒有調用對象的析構函數會導致系統資源不被釋放,這些資源的釋放必須依靠這些類的析構函數。所以,在用這些類生成對象數組的時候,用 delete[] 來釋放它們才是王道。而用 delete 來釋放也許不會出問題,也許后果很嚴重,具體要看類的代碼了。

本文轉載自微信公眾號「C語言與CPP編程」,可以通過以下二維碼關注。轉載本文請聯系C語言與CPP編程公眾號。

 

責任編輯:武曉燕 來源: C語言與CPP編程
相關推薦

2020-06-18 10:48:44

Linux 系統 數據

2021-09-06 07:58:47

鏈表數據結構

2018-03-28 21:40:03

2024-12-31 00:00:15

2011-04-11 09:47:50

C++內存管理

2021-06-16 00:57:16

JVM加載機制

2022-02-18 06:56:18

Wi-Fi路由器局域網

2023-12-12 13:13:00

內存C++編程語言

2011-07-01 10:16:08

C++內存管理

2020-10-09 09:49:18

HTTPS網絡 HTTP

2019-06-22 09:50:26

2025-10-27 01:33:00

2010-01-15 17:38:37

C++語言

2010-02-04 15:41:10

C++內存管理

2017-02-09 19:45:07

Linux系統Linux 發行版

2023-08-09 09:03:49

CPU密集型運算

2018-05-15 11:14:07

面試官C++編程

2010-01-14 10:23:08

C++語言

2010-01-13 17:04:36

C++語言

2010-01-26 10:27:43

C++語言
點贊
收藏

51CTO技術棧公眾號

一区二区三区回区在观看免费视频| 亚洲色图在线播放| 国产精品国产三级国产专播精品人| 精品人妻无码一区| 国产视频网站一区二区三区| 亚洲在线一区二区三区| 日韩欧美一区二区三区四区五区| 国产又粗又长视频| 久久精品一区二区国产| 不卡av在线网站| 亚洲天堂久久新| 无人区乱码一区二区三区| 欧美视频国产精品| 国产精品igao激情视频| 成人免费在线视频网| 粉嫩13p一区二区三区| 国产成人在线视频| 亚洲精品在线观看av| 成人久久久久| 精品亚洲aⅴ在线观看| 精产国品一二三区| 91大神在线观看线路一区| 亚洲福中文字幕伊人影院| 中文字幕日韩一区二区三区不卡| 三级国产在线观看| 粉嫩av一区二区三区在线播放| 国产精品久久久久久久一区探花 | 欧美精品videos| 中文字幕在线观看二区| 香蕉久久夜色精品国产使用方法| 日韩精品一区二区三区在线| 五月天婷婷亚洲| 日本精品不卡| 色综合天天狠狠| 缅甸午夜性猛交xxxx| 欧美xxx黑人xxx水蜜桃| 1024精品合集| 中文字幕免费在线不卡| 91吃瓜网在线观看| 国产欧美一区二区精品婷婷 | 99久久综合网| 伊人久久大香| 欧美精品日韩一区| 国产一级片自拍| 亚洲毛片在线免费| 777午夜精品免费视频| 一级黄色特级片| 高清欧美日韩| 欧美日韩一区二区三区在线 | 亚洲一级免费视频| av男人的天堂av| 九九久久婷婷| 亚洲片在线资源| 日本少妇xxxxx| 欧美综合视频| 俺也去精品视频在线观看| 91视频免费看片| 欧美疯狂party性派对| 日韩中文娱乐网| 任我爽在线视频| 中文字幕乱码亚洲无线精品一区| 欧美成人高清视频| 国产一级一级片| 国产精品久久久亚洲一区| 欧美亚洲日本黄色| 亚洲精品毛片一区二区三区| 蜜桃在线一区二区三区| 国产日韩欧美中文| a天堂中文在线观看| 粉嫩13p一区二区三区| 精品产品国产在线不卡| 精品欧美不卡一区二区在线观看| 国产日韩综合av| 麻豆中文字幕在线观看| 性xxxxfjsxxxxx欧美| 亚洲一区二区黄色| 日日摸日日碰夜夜爽无码| 都市激情亚洲一区| 欧美群妇大交群中文字幕| 手机在线免费毛片| 日韩精品福利一区二区三区| 亚洲人成在线一二| www.97视频| 99精品免费网| 成人高清视频观看www| 亚洲精品国产suv一区| 91蜜桃视频在线| 亚洲一区二区三区乱码| 青春草免费在线视频| 一本大道av伊人久久综合| 手机免费av片| 丝袜久久网站| 久久精品在线视频| 国产精品视频免费播放| 精品一区二区日韩| 久久久精品国产一区二区三区| 国产h视频在线观看| 亚洲午夜在线电影| 国产又黄又猛又粗| 果冻天美麻豆一区二区国产| 在线观看视频99| 日本少妇xxxx动漫| 久久草av在线| 免费观看成人在线| 直接在线观看的三级网址| 色婷婷久久久综合中文字幕| 波多野结衣三级视频| av资源久久| 97免费在线视频| 国产精品视频一二区| 久久综合九色综合久久久精品综合| 制服诱惑一区| 日韩精品免费观看视频| 亚洲国产日韩精品在线| 一区二区三区四区五区| 日韩和欧美的一区| 久久婷婷开心| 成人av影院在线观看| 51久久夜色精品国产麻豆| 中文字幕人妻一区二区| 亚洲第一伊人| 成人h在线播放| 91在线中字| 欧美日韩国产一区二区三区地区| 久久精品国产亚洲av久| 国产欧美欧美| 国产在线观看一区| 国产白丝在线观看| 精品人在线二区三区| www深夜成人a√在线| 美国一区二区三区在线播放 | 中文字幕av亚洲精品一部二部| 国产精品久久久久久久久久久久| 人妻精品一区一区三区蜜桃91| 亚洲男同性恋视频| 一二三av在线| 五月开心六月丁香综合色啪| 国产精品日韩精品| wwwww在线观看免费视频| 色呦呦网站一区| 久久久久亚洲av成人无码电影| 亚洲自拍另类| 欧美精品七区| av有声小说一区二区三区| 亚洲网站在线看| 亚洲精品国产无码| 中文字幕精品综合| 第四色婷婷基地| 国产精品88久久久久久| 成人午夜黄色影院| 午夜小视频福利在线观看| 日韩精品一区二区三区老鸭窝| 欧美成人精品欧美一| 国产成人免费xxxxxxxx| 999一区二区三区| 国产+成+人+亚洲欧洲在线| 国模私拍一区二区三区| 日av在线播放| 91福利资源站| 999精品在线视频| 国产剧情一区在线| 97超碰国产精品| 欧美网色网址| 国产精品999999| 日韩美女网站| 欧美tk—视频vk| 日本va欧美va国产激情| 久久久精品综合| 中文字幕 欧美日韩| 国产精品videosex极品| 久久久久久a亚洲欧洲aⅴ| 精品三区视频| 美女999久久久精品视频 | 在线免费看av不卡| 国产精品一区二区免费视频| 一区二区欧美国产| 亚洲第一成人网站| 国精产品一区一区三区mba视频| 91动漫在线看| 黑丝美女一区二区| 91视频在线免费观看| sis001欧美| 久久躁日日躁aaaaxxxx| 亚洲日本在线播放| 欧美一区二区三区视频在线观看 | 在线免费av一区| 久久免费看少妇高潮v片特黄| 北条麻妃一区二区三区| 亚洲天堂av线| 99国内精品| 中文字幕乱码一区二区三区| 欧美日韩直播| 亚洲最大的免费| 欧美xoxoxo| 欧美极品少妇xxxxⅹ喷水| 国产在线小视频| 欧美va在线播放| 一二三四区在线| 欧美日韩亚洲精品内裤| 国产美女福利视频| 久久亚洲私人国产精品va媚药| 日本一区二区三区在线免费观看| 性一交一乱一区二区洋洋av| 欧洲美女和动交zoz0z| 中文有码一区| 成人午夜电影在线播放| 色综合视频一区二区三区日韩| 91av在线看| 男女在线视频| www欧美日韩| 国产精品一区二区婷婷| 337p日本欧洲亚洲大胆精品| 一级全黄少妇性色生活片| 精品日本美女福利在线观看| 青青草国产在线观看| 国产精品视频第一区| 搡老熟女老女人一区二区| 国产成人啪免费观看软件| 午夜剧场高清版免费观看| 久久激情一区| www黄色日本| 在线精品亚洲| 欧美一区二区视频在线播放| 亚洲二区三区不卡| 亚洲国产精品一区在线观看不卡 | 免费视频观看成人| 日本久久久久久久| 日本在线啊啊| 97人洗澡人人免费公开视频碰碰碰| 成人av黄色| 久久精品99久久香蕉国产色戒| 成人在线观看免费| 国产一区二区日韩| 免费观看成年在线视频网站| 日韩精品在线看| 日本v片在线免费观看| 日韩av影片在线观看| 精品人妻一区二区三区换脸明星| 欧美夫妻性生活| 国产精选久久久| 日韩一区二区三区观看| 99热这里只有精品9| 91精品国产色综合久久| 99热这里只有精品3| 欧美一级在线观看| 亚洲av少妇一区二区在线观看| 日韩写真欧美这视频| 亚洲av无码一区二区乱子伦| 日韩精品影音先锋| 日本韩国在线观看| 日韩精品视频免费| 女人天堂在线| 中文在线资源观看视频网站免费不卡| 国产乱理伦片a级在线观看| 国产亚洲欧洲高清一区| 午夜在线视频播放| 久久精品视频在线播放| 在线视频国产区| 国产+成+人+亚洲欧洲| 国产理论在线| 国产999精品久久久| 韩国理伦片久久电影网| 成人妇女淫片aaaa视频| 日本一区影院| 国外成人在线视频网站| 婷婷综合福利| 一本色道久久99精品综合| 99久久久久国产精品| 成人黄色片免费| 国产一区二区三区久久久久久久久 | 一区二区毛片| 人人爽人人av| 国产精品亚洲人在线观看| 中文字幕一区三区久久女搜查官| 久久久亚洲综合| 老司机成人免费视频| 亚洲成人av一区二区| 亚洲天堂视频在线播放| 欧美一区二区啪啪| 天堂a中文在线| 日韩性生活视频| av日韩国产| 国产美女高潮久久白浆| 亚洲小说春色综合另类电影| 欧美黑人xxxxx| 91精品啪在线观看国产18| 人妻久久久一区二区三区| 免费精品视频最新在线| youjizz.com国产| 国产午夜精品一区二区三区四区| 日韩三级在线观看视频| 欧美日韩激情小视频| 国产美女永久免费| 亚洲美女中文字幕| 手机av在线播放| 国产精品免费观看在线| 粉嫩久久久久久久极品| 这里只有精品66| 老司机免费视频久久| 麻豆传媒在线看| 国产精品视频在线看| 国产精品一区二区6| 91精品国产综合久久久蜜臀图片| 青青九九免费视频在线| 欧美日韩成人黄色| 国产一区二区色噜噜| 国新精品乱码一区二区三区18| 亚洲精品久久| 亚洲天堂网一区| 久久精品夜色噜噜亚洲aⅴ| 精品午夜福利视频| 欧美日韩aaa| 国产视频二区在线观看| 国语自产精品视频在线看一大j8| 成人噜噜噜噜| 日韩少妇中文字幕| 免费中文字幕日韩欧美| 香蕉视频污视频| 一区二区成人在线观看| 国产精品久久久久久免费免熟 | 欧美日韩色综合| 欧美男男激情freegay| 欧美极品少妇xxxxⅹ喷水| 久久天堂久久| 亚洲免费视频播放| 精品制服美女久久| 国产精品一区二区亚洲| 在线观看区一区二| 国产综合在线观看| 欧美在线一级va免费观看| 欧美91在线| 黄色一级在线视频| 91一区一区三区| 欧美一区二区激情视频| 亚洲国内精品在线| 3344国产永久在线观看视频| 丁香五月网久久综合| 国产精品久久| xfplay5566色资源网站| 亚洲午夜在线视频| 天堂中文在线资源| 欧美一区二区三区艳史| 亚洲妇女av| 欧美 日韩 国产 激情| 国产欧美一区二区精品性| 国产精品无码一区| 日韩中文字幕av| 婷婷久久免费视频| 99re6这里有精品热视频| 国产经典欧美精品| 国产午夜福利片| 日韩精品视频在线观看网址| 都市激情亚洲一区| 一本久道久久综合| 国产成人午夜电影网| 日本熟妇毛茸茸丰满| 日韩电影免费观看中文字幕| 韩国久久久久久| 五月天亚洲综合小说网| 国产在线精品视频| 精品人妻在线播放| 日韩精品在线观看一区二区| 97精品国产99久久久久久免费| 一区二区不卡在线观看| 国产乱理伦片在线观看夜一区| 日本在线视频免费观看| 国产一区二区三区在线播放免费观看| 美女色狠狠久久| av动漫在线播放| 91在线视频免费观看| 久久国产香蕉视频| 精品中文字幕在线2019| 欧美三级午夜理伦三级小说| 免费看污黄网站| 一区二区三区.www| 免费在线毛片| 亚洲精品免费网站| 免费中文字幕日韩欧美| 国产美女福利视频| 亚洲开心激情网| 国产不卡精品| av动漫在线看| 综合久久久久久| 深夜福利在线看| 成人免费网站在线观看| 99亚洲精品| 永久免费看mv网站入口| 精品视频—区二区三区免费| 亚洲一区二区av| 青青草原成人网| 一区二区在线免费观看| 激情小说 在线视频| www.成人三级视频| 日韩精品福利网| 一级aaa毛片| 久久精品国亚洲| 伊人春色精品| 色诱av手机版| 欧美区视频在线观看| 亚洲欧美se|