指向對象的指針


//以前學這些內容的時候覺得好難理解啊,現在再看這些知識點,實在輕松了不少,敲一遍博客,感覺理解更深了: )

我們知道,對象一經聲明就為對象的成員分配存儲空間,並調用其構造函數進行初始化,對象生存期結束后自動調用其析構函數,並釋放對象占用的內存空間。沒有什么辦法控制什么時候調用對象的構造函數,也沒有辦法決定什么時候釋放對象占用的存儲空間。如果在程序中需要使用許多對象,並且這些對象均占用大量存儲空間,就會造成內存緊張。

一種比較好的解決途徑是釋放先聲明這些對象,但並不立即分配存儲空間和調用構造函數,在需要這些對象時才這么做,使用完這些對象后立即調用其析構函數並釋放其占用的存儲空間,而不是留待對象生存期結束后才由C+系統自動回收存儲空間。這一途徑是使用C++語言指向對象的指針。

先定義一個類:

class PTRCLASS{
public:
    void setX(int y){       //設置X的值
        x = y;
    }
    int getX(){     //取得x的值
        return x;
    }
private:
    int x;
}

對象指針

如果聲明的一個指針的基類型是一個類類型,那么這個指針被稱為對象指針,它指向一個對象。如:

int PTRCLASS *ptr;

聲明了一個對象指針ptr,這個指針只能指向一個PTRCLASS類型的對象。注意這時C++僅僅為這個指針分配了存放指針值的存儲空間,並沒有分配存放一個屬於PTRCLASS類型的內存空間。

與其他基本數據類型的變量相似,可以用&運算符取一個對象的地址,然后賦值給一個對象指針:

PTRCLASS p; ptr = &p;

這時,對象指針ptr指向對象p,可以使用運算符“->”訪問這個對象的共有數據成員或成員函數,如:

ptr -> getX();

在C++中語言一個類的成員函數體中都隱含提供了一個對象指針this,它指向該成員函數正在操作的對象。

int PTRCLASS::getX()
{
    return x;
}

等價於:

int PTRCLASS::getX()
{
    return this->x;
}

對象的動態創建與撤銷

C++也可以使用newdelete運算符完成對象的動態創建與撤銷。
運算符new的一般形式為:

指針 = new 類型名(初始化表);

其中,初始化表及其括號是可選內容,類型既可以是基本數據類型,也可以是類類型,如果是類類型,則初始化列表相當於將實際參數傳遞給該類的構造函數。如:

PTRCLASS *ptr = new PTRCLASS;

表示用new為指針ptr分配了內存空間。
用new分配內存空間並不能保證每一次都成功。例如,當前沒有足夠的內存資源可供分配,這有可能是請求的內存太多、硬件資源不足,也有可能是程序出錯,一直在分配內存卻沒有釋放內存。

一個良好的習慣是在每次new操作后都判斷內存分配是否成功,如:

PTRCLASS *ptr = new PTRCLASS;
if(!ptr){   //等價於ptr == NULL
    //內存分配失敗時的出錯處理
}else{
    //內存成功分配時的動作
}

如果不再需要所分配的存儲空間時,可以使用delete釋放他們:

delete ptr;

對於基本數據類型,也和類類型相似,如:

int *int_ptr;
int_ptr = new int;

分配了2個字節的存儲空間,並將基類型為int的指針指向這個存儲空間的起始地址。又如:

char *string;
string = new char[40];
//上述語句等價於
char *string = new char[40]

將為字符串變量string分配40個字節的存儲空間,並使string指向這個空間的起始地址。

注意這里與靜態聲明數組的區別:聲明靜態數組時方括號內只允許出現常量表達式,而new則允許在表達式中使用變量。

如果使用new運算申請的是一個類類型對象的數組,如:

ptr = new PTRCLASS[40];

則使用delete運算釋放時應加上方括號對[],以確保調用數組中每一個PTRCLASS對象的析構函數:

delete[] ptr;

使用對象的指針應注意的

當程序中不再需要使用分配來的內存空間時,一定要記住釋放這些空間。如果這些空間不釋放,那么在整個程序的運行過程中,這些內存一直被占用,無法再分配給其他程序。如果指向這一存儲空間的指針的值被改變,或該指針的作用域與生存期結束,將無法釋放這些空間。這些無法再回收的存儲空間稱為內存垃圾,內存垃圾的不斷增加將會耗盡所有內存,最終會導致系統崩潰!

在使用對象指針時還應盡量避免使用別名。使用別名有潛在的危險,如:

int *ptr1;
int *ptr2;
...
ptr1 = new int;     //申請空間並將ptr1指向分配到的空間
ptr2 = ptr1;        //使ptr2指向與ptr1相同的地址

如果此時再執行:

delete ptr1;

將會使兩個指針都變為無效的,如果繼續使用ptr2,將會導致內存混亂。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM