多個指針指向同一個地址


  • 多個指針指向同一個地址,這樣使用沒什么問題,只是操作時要注意。
  • 因為,每個指針變量保存的值,僅僅是指向的內容的地址值。多個指向同一個地址的指針,若其中一個指針等於NULL,不影響另一個指針。
int* a = new int(10);
int* c = a;

delete c; // 指向的那塊內存內容(new int(10)釋放 
c = NULL // 僅讓c的值變為 null, a的值(地址)未變

if (a != NULL) {
    // 此處代碼仍會函數體仍會執行!!!
}

 

https://blog.csdn.net/u011301123/article/details/9293297?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param


 

眾所周知,最開始我們用new來創建一個指針,那么等我們用完它之后,一定要用delete將該指針刪掉。但是,值得注意的是,難道就僅僅是刪除這個指針這么簡單的么?下面,我們用一個程序來說明這個問題:

#include
02
using namespace std;
03
int main()
04
{
05
    int *p=new int;
06
    *p=3;
07
    cout<<"將3賦給p的地址后,指針p讀取的值:"<<*p<<endl;
08
    delete p;
09
    cout<<"刪除空間后,指針p讀取的值:"<<*p<<endl;
10
    long *p1=new long;
11
    *p1=100;
12
    cout<<"創建新空間后,指針p中保存的地址:"<<p<<endl;
13
    cout<<"指向新空間的指針p1保存的地址:"<<p1<<endl;
14
    *p=23;
15
    cout<<"將23賦給p的地址后,指針p讀取的值:"<<*p<<endl;
16
    cout<<"將23賦給p的地址后,指針p1讀取的值:"<<*p1<<endl;
17
    delete p1;
18
    return 0;
19
}

在上面這個程序中,我們在第8行就將指針p利用delete刪掉了。但是,我們來看看程序的輸出結果:

      對照着上面的程序,我們來分析一下這個輸出。首先,我們在程序的第5行初始化了一個指針p。之后輸出指針p讀取的值。由於第6行的原因,程序肯定會輸出3 了。之后,我們在程序的第8行刪除了這個指針p。但是我們驚奇的發現,在程序的第9行竟然可以輸出指針p讀取的值。我們不是已經把它刪了么?其實不 然,debug,上圖:

 

從監視窗口中,我們可以看見雖然程序的第8行已經將指針p刪除了,但是在監視窗口中p仍然存在,只是*p所指向的值不再是原來的3了,而是一個隨機數。這里就說明了一個非常重要的概念:我們在刪除一個指針之后,編譯器只會釋放該指針所指向的內存空間,而不會刪除這個指針本身。

      然后我們接着往下分析。在程序的第10行我們又創建了一個long型的指針p1。在12行與13行的輸出中我們驚奇地發現,指針p保存的地址居然和指針 p1保存的地址一模一樣!這個就說明了指針p和指針p1都指向內存的同一個地方!!!出現這種狀況的原因其實是由於編譯器。編譯器默認將釋放掉的內存空間回收然后分配給新開辟的空間。所 以在第11行由於我們新開辟了一個可以保存long型變量的空間並且由p1來指向它,那么這里的p1指向的其實就是在程序第8行釋放掉的內存空間,即p指 向的內存空間!所以,這就導致了兩個指針同時指向同一個內存空間。這是多不安全的一件事情啊!要知道,我們是把指針p刪了的啊!如果再重新對*p進行賦值 操作,那么不是會連着*p1一起改動么?

      果然,讓我們擔心的事情出現了。我們明明在程序的第11行中定義了*p1的值為100,但是在輸出上面,指針p1讀取的值竟然也是23。這個原因就是因為 野指針p造成的。我們可以看到,在程序的第14行我們將23賦給了*p。又由於p和p1指向的是同一塊內存單元,所以在這里相當於也將p1所指向的內存單 元中的值(原來是100),改成了23!這樣必然會導致程序的出錯!

       那么我們就不禁要問了,對於這種由於野指針造成的問題,有沒有解決的方法呢?答案當然是有的了。我們只需要牢記下面這句話:

在刪除一個指針之后,一定將該指針設置成空指針(即在delete *p之后一定要加上: p=NULL)

      我們來看一下在stdio.h中關於關鍵字NULL的定義:

#ifndef NULL
#ifdef __cplusplus
#define NULL    0
#else
#define NULL    ((void *)0)
#endif
#endif

注意上面定義的第5行。這里其實就說明了NULL就是0。也就是說,我們在刪除完指針p之后,一定要把它變成空指針!只有這樣,才會杜絕上面程序中出現的野指針的錯誤。

p.s. 對於NULL的應用,我們不應該僅限於上面的方法,還可以應用NULL來判斷指針是否初始化成功了,如下例if中的判斷方法:

#include
02
using namespace std;
03
 
04
int main()
05
{
06
    int *p=new int;
07
    if (p==NULL)
08
    {
09
        //判斷指針p是不是空指針,如果是空指針,那么程序在這里就應該報錯
10
        //報錯的方法有很多,比如說返回一個ERROR值:
11
        //return ERROR;
12
    }
13
 
14
    //判斷了操作成功之后我們才能進行一系列的操作
15
    //...
16
 
17
    //用完指針p之后,一定要將其刪掉。這樣可以杜絕野指針的存在
18
    delete p;
19
    //刪除指針p之后,一定要加上下面這句話,免得成為野指針
20
    p=NULL;
21
}

好了,下次一定要記住,在分配空間給指針之后,一定要用NULL來判斷一下是否成功了。然后在刪除這個指針的時候,也要用NULL來賦給指針,杜絕成為野指針!

 


免責聲明!

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



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