了解動態記憶體在 C++ 中是如何作業的是成為一名合格的 C++ 程式員必不可少的,C++ 程式中的記憶體分為兩個部分:
- 堆疊:在函式內部宣告的所有變數都將占用堆疊記憶體,
- 堆:這是程式中未使用的記憶體,在程式運行時可用于動態分配記憶體,
很多時候,您無法提前預知需要多少記憶體來存盤某個定義變數中的特定資訊,所需記憶體的大小需要在運行時才能確定,
常見的動態記憶體分配方式:
在 C++ 中,您可以使用特殊的運算子為給定型別的變數在運行時分配堆內的記憶體,這會回傳所分配的空間地址,這種運算子即 new 運算子,
如果您不再需要動態分配的記憶體空間,可以使用 delete 運算子,洗掉之前由 new 運算子分配的記憶體,
new 和 delete 運算子
下面是使用 new 運算子來為任意的資料型別動態分配記憶體的通用語法:
new data-type;
在這里,data-type 可以是包括陣列在內的任意內置的資料型別,也可以是包括類或結構在內的用戶自定義的任何資料型別,讓我們先來看下內置的資料型別,例如,我們可以定義一個指向 double 型別的指標,然后請求記憶體,該記憶體在執行時被分配,我們可以按照下面的陳述句使用 new 運算子來完成這點:
double* pvalue = NULL; // 初始化為 null 的指標
pvalue = new double; // 為變數請求記憶體
如果自由存盤區已被用完,可能無法成功分配記憶體,所以建議檢查 new 運算子是否回傳 NULL 指標,并采取以下適當的操作:
double* pvalue = NULL;
if( !(pvalue = new double ))
{
cout << "Error: out of memory." <<endl;
exit(1);
}
malloc() 函式在 C 語言中就出現了,在 C++ 中仍然存在,但建議盡量不要使用 malloc() 函式,new 與 malloc() 函式相比,其主要的優點是,new 不只是分配了記憶體,它還創建了物件,
在任何時候,當您覺得某個已經動態分配記憶體的變數不再需要使用時,您可以使用 delete 運算子釋放它所占用的記憶體,如下所示:
delete pvalue; // 釋放 pvalue 所指向的記憶體
下面的實體中使用了上面的概念,演示了如何使用 new 和 delete 運算子:
#include <iostream>
using namespace std;
int main ()
{
double* pvalue = NULL; // 初始化為 null 的指標
pvalue = new double; // 為變數請求記憶體
*pvalue =https://www.cnblogs.com/h88999/p/ 29494.99; // 在分配的地址存盤值
cout << "Value of pvalue : " << *pvalue << endl;
delete pvalue; // 釋放記憶體
return 0;
}
當上面的代碼被編譯和執行時,它會產生下列結果:
Value of pvalue : 29495
malloc和free
1. 定位
malloc為C語言stdlib.h庫中的函式,可以用于動態申請空間,在申請空間之后不會對記憶體進行必要的初始化,
C++可以兼容大部分C語言的內容,malloc/free這一申請/釋放動態記憶體的方式在C++中用也是可以使用的,
2. 基本語法:
變數申請示例
char * buffer;
buffer = (char*)malloc(i + 1)
用于以位元組為單位進行記憶體分配,不具備記憶體初始化特性,回傳指標的型別為void*,可以通過型別轉換(如static_cast<type>、(type)等)轉換為想要的型別,
陣列的動態記憶體分配
假設我們要為一個字符陣列(一個有 20 個字符的字串)分配記憶體,我們可以使用上面實體中的語法來為陣列動態地分配記憶體,如下所示:
char* pvalue = NULL; // 初始化為 null 的指標
pvalue = new char[20]; // 為變數請求記憶體
要洗掉我們剛才創建的陣列,陳述句如下:
delete [] pvalue; // 洗掉 pvalue 所指向的陣列
下面是 new 運算子的通用語法,可以為多維陣列分配記憶體,如下所示:
一維陣列
// 動態分配,陣列長度為 m
int *array=new int [m];
//釋放記憶體
delete [] array;
二維陣列
int **array
// 假定陣列第一維長度為 m, 第二維長度為 n
// 動態分配空間
array = new int *[m];
for( int i=0; i<m; i++ )
{
array[i] = new int [n] ;
}
//釋放
for( int i=0; i<m; i++ )
{
delete [] arrary[i];
}
delete [] array;
二維陣列實體測驗:
#include <iostream>
using namespace std;
int main()
{
int **p;
int i,j; //p[4][8]
//開始分配4行8列的二維資料
p = new int *[4];
for(i=0;i<4;i++){
p[i]=new int [8];
}
for(i=0; i<4; i++){
for(j=0; j<8; j++){
p[i][j] = j*i;
}
}
//列印資料
for(i=0; i<4; i++){
for(j=0; j<8; j++)
{
if(j==0) cout<<endl;
cout<<p[i][j]<<"\t";
}
}
//開始釋放申請的堆
for(i=0; i<4; i++){
delete [] p[i];
}
delete [] p;
return 0;
}
三維陣列
int ***array;
// 假定陣列第一維為 m, 第二維為 n, 第三維為h
// 動態分配空間
array = new int **[m];
for( int i=0; i<m; i++ )
{
array[i] = new int *[n];
for( int j=0; j<n; j++ )
{
array[i][j] = new int [h];
}
}
//釋放
for( int i=0; i<m; i++ )
{
for( int j=0; j<n; j++ )
{
delete[] array[i][j];
}
delete[] array[i];
}
delete[] array;
三維陣列測驗實體:
#include <iostream>
using namespace std;
int main()
{
int i,j,k; // p[2][3][4]
int ***p;
p = new int **[2];
for(i=0; i<2; i++)
{
p[i]=new int *[3];
for(j=0; j<3; j++)
p[i][j]=new int[4];
}
//輸出 p[i][j][k] 三維資料
for(i=0; i<2; i++)
{
for(j=0; j<3; j++)
{
for(k=0;k<4;k++)
{
p[i][j][k]=i+j+k;
cout<<p[i][j][k]<<" ";
}
cout<<endl;
}
cout<<endl;
}
// 釋放記憶體
for(i=0; i<2; i++)
{
for(j=0; j<3; j++)
{
delete [] p[i][j];
}
}
for(i=0; i<2; i++)
{
delete [] p[i];
}
delete [] p;
return 0;
}
物件的動態記憶體分配
物件與簡單的資料型別沒有什么不同,例如,請看下面的代碼,我們將使用一個物件陣列來理清這一概念:
#include <iostream>
using namespace std;
class Box
{
public:
Box() {
cout << "呼叫建構式!" <<endl;
}
~Box() {
cout << "呼叫解構式!" <<endl;
}
};
int main( )
{
Box* myBoxArray = new Box[4];
delete [] myBoxArray; // 洗掉陣列
return 0;
}
如果要為一個包含四個 Box 物件的陣列分配記憶體,建構式將被呼叫 4 次,同樣地,當洗掉這些物件時,解構式也將被呼叫相同的次數(4次),
當上面的代碼被編譯和執行時,它會產生下列結果:
呼叫建構式!
呼叫建構式!
呼叫建構式!
呼叫建構式!
呼叫解構式!
呼叫解構式!
呼叫解構式!
呼叫解構式!
如果這篇文章對你有用的話,關注下圖了解更多幫助你更好的學習編程噢~海量免費資源+技術指導

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/251337.html
標籤:C++
上一篇:【程式員進階】如何才能減少 C++ 代碼編譯時間的方法!
下一篇:Qt跨平臺編程之中文編碼問題
