首先我們先來瞭解一下MFC中的CPtrArray類,他可以說是CObject類型指標對象的集合。通過int Add( CObject* newElement );注意參數是一個指標類型)可以向集合中添加元素。首先我們定義一個CPtrArray類型的對象。
CPtrArray pArray;//他是一個全域對象
先設定一個舉例的類類型。如:
class A{public:A(int i){a = i;}~A(){}public:int a;};
現在我們需要在某個函數中要實現將一個A類型對象資料加入到一個CPtrArray對象中。此函數func1()如下:
void func1(){//首先定義一個A類型的對象A a(1);//使用pArray對象中的成員函數將此對象加入到容器中pArray.Add(&a);}
在另一個函數中我們使用pArray容器為我們儲存的資料:
void func2(){//首先聲明一個A類型的對象A* a;//使用pArray對象中的成員函數GetAt()將A類型的對象取出for(int i; i < pArray.GetSize();i++){a = (A*)pArray.GetAt(i);//使用A中的資料進行相關的作業碼。***此時也可以使用delete釋放指標指向的記憶體區塊,防止記憶體泄露***當然是後面一種方法時才用到,暫時無視之。...}}
現在我們發現按照上面的過程,當我們在func2()函數中將要使用pArray容器物件為我們儲存的資料時,我們並不能得到想要的資料!!!為什麼發生以上情況?圖解如下
pArray儲存a儲存資源的地址;
func1函數執行完成,a發生析構,資源不可用;
原來在func1()函數中,a對象是一個局部對象,當我們使用pArray.Add(&a);我們將a對象的地址儲存到pArray對象中。但是作為局部對象,當func1
執行完成後,資源需要回收,此時我們定義的a對象也在A類中的解構函式中被析構釋放資源!而當我們在fun2()函數中執行取出儲存的對象時,
實際是根據儲存的地址去記憶體中找到資料,雖然此時我們能能夠找到此地址,但是這個地址上面的資料並不是我們需要的了!!!所以才發生面的情況!
那麼怎麼才能解決呢?
看下面,我們只需更改func1函數中的代碼:
void func1(){//首先定義一個A類型的對象//A a(1);//為對比,只是注釋原來那句A* a = new A(1);//使用pArray對象中的成員函數將此對象加入到容器中pArray.Add(a);}
這樣,我們就能夠在func2函數中使用pArray對象中包含的資料了!那麼為什麼定義了一個指標類型的對象就能夠完成了呢?還是一個局部對象呀,
前面說的func1函數執行完成後此對象還是要經曆析構的啊!圖解如下:
pArray中儲存a指向資源的地址;
func1函數執行完成,a對象發生析構,pArray根據地址還能能夠訪問到之前的資源;
對,是要析構,但是,我們在pArray.Add(a);中加入的是a對象資源的地址,我們先看看A* a = new A(1);在堆中分配資源,我們知道,在堆中分配的資
源是在跟程式的生命週期是一致的。a對象雖然析構了(不存在了),因為a也是一個指標,a指標也就是儲存這個資源的地址!我們在pArray中儲存
的a的地址出的資源並沒有析構!所以在func2函數中我們還能夠使用此地址訪問此地址對應的資源!