C++ 動態內存分配詳解(new/new[]和delete/delete[])

一、為什麼需要動態內存分配?

在C++程序中,所有內存需求都是在程序執行之前通過定義所需的變量來確定的。 但是可能存在程序的內存需求隻能在運行時確定的情況。 例如,當需要的內存取決於用戶輸入。 在這些情況下,程序需要動態分配內存,C ++語言將運算符new和delete合成在一起。

(1)特點

  • 1.C++中通過new關鍵字進行動態內存申請
  • 2.C++中的動態內存分配是基於類型進行的
  • 3.delete關鍵字用於內存釋放

(2)語法

①變量申請:

Type* pointer = new Type;
//...
delete pointer;

  表達式用於分配內存以包含一個類型類型的單個元素。

②數組申請:

Type* pointer = new Type[N];
//...
delete[] pointer;

表示用於分配類型類型的元素的塊(數組),其中N是表示這些元素的量的整數值。

Example:

int * foo;
foo = new int [5];

在這種情況下,系統為int類型的五個元素動態分配空間,並返回指向序列的第一個元素的指針,該指針被分配給foo(指針)。 因此,foo現在指向一個有效的內存塊,其中包含五個int類型元素的空間。

  這裡,foo是一個指針,因此,foo指向的第一個元素可以使用表達式foo [0]或表達式* foo(兩者都是等價的)來訪問。可以使用foo [1]或*(foo + 1)訪問第二個元素,依此類推…… 

Note:

  我們程序請求的動態內存由系統從內存堆中分配。 但是,計算機內存是一種有限的資源,它可能會耗盡。 因此,無法保證所有使用operator new分配內存的請求都將由系統授予。

(3)動態內存分配Example:

#include <stdio.h>
 
int main()
{
    int* p = new int;
    
    *p = 5;
    *p = *p + 10;
    
    printf("p = %p\n", p);
    printf("*p = %d\n", *p);
    
    delete p;
    
    p = new int[10];
    
    for(int i=0; i<10; i++)
    {
        p[i] = i + 1;
        
        printf("p[%d] = %d\n", i, p[i]);
    }
    
    delete[] p;
    
    return 0;
}

編譯運行,結果:

p = 007F77D8
*p = 15
p[0] = 1
p[1] = 2
p[2] = 3
p[3] = 4
p[4] = 5
p[5] = 6
p[6] = 7
p[7] = 8
p[8] = 9
p[9] = 10
請按任意鍵繼續. . .

二、new關鍵字與malloc函數的區別

new關鍵字是C++的一部分 malloc是由C庫提供的函數
new以具體類型為單位進行內存分配 malloc以字節為單位進行內存分配
new在申請單個類型變量時可進行初始化 malloc不具備內存初始化的特性

三、new關鍵字的初始化:

    int* pi = new int(1);
    float* pf = new float(2.0f);
    char* pc = new char('c');

Test:

#include <stdio.h>
 
int main()
{
    int* pi = new int(1);
    // int* pa = new int[1];
    
    float* pf = new float(2.0f);
    char* pc = new char('c');
 
    printf("*pi = %d\n", *pi);
    printf("*pf = %f\n", *pf);
    printf("*pc = %c\n", *pc);
    
    delete pi;
    delete pf;
    delete pc;
    
    return 0;
}

輸出結果:

*pi = 1
*pf = 2.000000
*pc = c
請按任意鍵繼續. . .

註意:

int* pi = new int(1);表示動態分配一個int ,初始化為 1int* pa = new int[1];表示動態分配一個數組,數組大小為1

四、C++動態分配內存異常機制

    事項一下,我們的計算機內存優先,如果我們分配一個很大的內存空間,會出現棧滿,程序產生異常,程序崩潰。所以我們需要引入異常機制。

    C ++提供瞭兩種標準機制來檢查分配是否成功。

    (1)一個是處理異常。

  使用此方法,在分配失敗時拋出bad_alloc類型的異常。 例外是這些教程後面解釋的強大的C ++特性。 但是現在,您應該知道如果拋出此異常並且未由特定處理程序處理,則程序執行將終止。

    此異常方法是new默認使用的方法,並且是在聲明中使用的方法,like:

foo = new int [5];  // if allocation fails, an exception is thrown

  (2)另一種方法稱為nothrow

  當使用它時會發生的情況是,當內存分配失敗時,而不是拋出bad_alloc異常或終止程序,new返回的指針是空指針,程序繼續正常執行 。

  可以使用名為nothrow的特殊對象(在header <new>中聲明)作為new的參數來指定此方法:

foo = new (nothrow) int [5];

在這種情況下,如果此內存塊的分配失敗,則可以通過檢查foo是否為空指針來檢測異常:

int * foo;
foo = new (nothrow) int [5];
if (foo == nullptr) {
  // error assigning memory. Take measures.
}

異常處理Example:

// rememb-o-matic
#include <iostream>
#include <new>
using namespace std;
 
int main ()
{
  int i,n;
  int * p;
  cout << "How many numbers would you like to type? ";
  cin >> i;
  p= new (nothrow) int[i];
  if (p == nullptr)
    cout << "Error: memory could not be allocated";
  else
  {
    for (n=0; n<i; n++)
    {
      cout << "Enter number: ";
      cin >> p[n];
    }
    cout << "You have entered: ";
    for (n=0; n<i; n++)
      cout << p[n] << ", ";
    delete[] p;
  }
  return 0;
}

編譯運行,結果:

參考資料:

1)唐佐林 《C++深度解析教程》

2)C++官網

到此這篇關於C++ 動態內存分配詳解(new/new[]和delete/delete[])的文章就介紹到這瞭,更多相關C++ 動態內存分配內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: