天天看點

C++ primer Plus書之--C++指針及使用new配置設定記憶體,使用delete釋放記憶體

先來個簡單的程式初步認識一下指針 

#include <iostream>
using namespace std;

int main() {
	// 定義一個int型變量
	int num = 123;
	// 定義一個int型指針變量
	int * p_num;
	// 指針指向num的位址
	p_num = &num;
	
	cout << "num = " << num << endl;
	cout << "*p_num = " << *p_num << endl;
	cout << "address of num is : " << &num << endl;
	cout << "p_num = " << p_num << endl;
	
	// 對p_num指向的位址裡的數+1
	// 那麼num的值也+1, 因為p_num指向的就是num的記憶體位址
	*p_num = *p_num + 1;
	cout << "num = " << num << endl;
	cout << "*p_num = " << *p_num << endl;
}
           

看運作結果:

C++ primer Plus書之--C++指針及使用new配置設定記憶體,使用delete釋放記憶體

注意使用指針的時候有個一定要注意的地方:一定要在對指針指向的記憶體進行指派之前, 對指針的位址進行初始化, 否則我們就不知道所賦的值存儲的具體位置是哪裡, 因為指針沒有被初始化, 是以指針指向的對我們來說是未知的位址, 而我們存儲的資料也将是在那塊未知的位址裡.  舉個例子:

long* p_longNum;
*p_longNum = 12345;
           

上面兩行代碼, 第一行聲明了一個long型指針, 第二行把12345指派給p_longNum所指向的位址, 但是問題是我們沒有給p_longNum初始化位址, 是以我們不知道p_longNum指向了哪個位址, 也就是我們隻初始化了指針變量, 而沒有對其初始化, 那麼p_longNum的值是記憶體當中原來已存在的數值, 這樣會有一些隐患

c++裡聲明指針可以是一下幾種方式:

int*  p_num1;
	int * p_num2;
	int *p_num3;
	int*p_num4;
           

int * p_num ,  中間的空格可有可無 

指針和數字

注意指針不是整型, 雖然計算機通常把位址當作整數來處理. 整數可以加減乘除等運算, 而指針描述的是位置, 是以将兩個位址相乘沒有任何意義.

int* pt;
pt = 0xB1000000;
           

看這個例子:雖然pt是一個int型指針, 可以給pt賦一個位址, 但是這條語句并沒有告訴程式, 這個數字就是一個位址, 是以這樣指派編譯機會報錯:

C++ primer Plus書之--C++指針及使用new配置設定記憶體,使用delete釋放記憶體

是以如果我們想把一個整型位址複制給指針可以通過強制類型轉換, 将數字轉換為合适的位址類型例如:

int* pt;
pt = (int *)0xB1000000;
           

 這樣等号兩邊都是整數位址, 就可以有效指派, 注意雖然pt是int型指針, 但是不代表pt本身的類型是int, 例如有些系統int占兩個位元組, 而指針占4個位元組

對指針指派的時候應該是将記憶體位址指派給指針, 可以對變量應用&運算符, 也可以使用new運算符來傳回未命名的記憶體位址

C++中使用new來配置設定記憶體

c++中我們可以使用new來進行記憶體的配置設定  格式如下:

typeName * pinter_name = new typeName;

來看一個簡單的例子:

#include <iostream>
using namespace std;

int main() {
	int num = 1000;
	// 聲明一個int型指針
	int* pt = new int;
	// 給pt指針指向的記憶體裡賦1000
	*pt = 1000;
	
	cout << "num is : ";
	cout << num << " and num's location is : " << &num << endl;
	cout << "int value is : " << *pt << " and it's location  is " << pt << endl;;
	
	// 聲明一個double類型的指針變量, 并配置設定了記憶體空間
	double * pd = new double;
	// 給pd指針指向的記憶體裡賦1000
	*pd = 10000001.0;
	cout << "double value is : " << *pd << " and it's location is : " << pd << endl;
	cout << "location of pointer pd : " << &pd << endl;
	cout << "size of pt = " << sizeof(pt) << endl;
	cout << "size of pd = " << sizeof(pd) << endl;
	cout << "size of *pt = " << sizeof(*pt) << endl;
	cout << "size of *pd = " << sizeof(*pd) << endl;
	return 0;
}
           

運作結果如下:

C++ primer Plus書之--C++指針及使用new配置設定記憶體,使用delete釋放記憶體

使用delete釋放記憶體

當需要記憶體時,可以使用new來配置設定記憶體,當使用完記憶體後可以使用delete來釋放new配置設定的記憶體,例如:

// 使用new給指針pn配置設定記憶體
int * pn = new int;
// 使用delete來釋放pn指針指向的記憶體
delete pn;
           

注意:釋放pn指向的記憶體,不會删除指針pn本身,也就是我們可以将pn重新指向另一個新配置設定的記憶體塊. 一定要配對的使用new和delete,否則将會發生記憶體洩漏(memory leak), 也就是說被配置設定的記憶體再也無法使用了, 如果記憶體洩漏嚴重, 程式将因為配置設定不到新記憶體而終止.

另外不要嘗試釋放已經釋放的記憶體塊例如:

int * pn = new int;
// 正确
delete pn;
// 不正确, 因為pn已經釋放過一次了
delete pn;
int num = 123;
int * pn2 = &num;
// 不正确, 因為pn的記憶體不是通過new來配置設定的
delete pn2;
           

注意:隻能用delete來釋放使用new配置設定的記憶體, 但是對空指針使用delete是安全的. 

int * pn = new int;
int * pn2 = pn;
delete pn2;
           

上面的代碼是沒有問題的, 但是一般來說不要建立兩個指向同一個記憶體的指針, 因為這将增加錯誤的删除同一個記憶體塊兩次的可能性

繼續閱讀