動態記憶體的管理是通過一對運算子來完成的:
- new,在動態記憶體中為物件分配空間并回傳一個指向改該物件的指標,
- delete,接收一個動態物件的指標,銷毀該物件,并釋放與之關聯的記憶體,
出現問題:不能確保在正確的時間釋放它:
- 有時候我們會忘記釋放記憶體,這種情況下會產生記憶體泄漏
- 有時候再尚有指標參考記憶體的時候指標被釋放了
因此就出現了智能指標,幫助我們進行指標的釋放,
auto_ptr的使用
auto_ptr就是第一個,但是由于其中的問題現在沒有了
auto_ptr使用方法:
- 在構造時獲取對某個物件的所有權(ownership),
- 在析構時釋放該物件,
上面說的是構造和析構,此時就出現了問題,如果兩個析構同時指向一個物件,那么當一個析構之后,另一個析構就發現沒有物件了,自然就出現了問題:
如下:
{ int *a = new int(10);
auto_ptr<int> b(a);
auto_ptr<int> c(a);}
此時這個大括號作用域結束之后,b物件呼叫析構之后,就將a洗掉了,此時c再呼叫析構就會發生錯誤了
第一個問題:
所以我們需要注意了,兩個auto_ptr不能同時擁有同一個物件,
拷貝構造與賦值
auto_ptr要求其對“裸”指標的完全占有性,也就是說一個“裸”指標不能同時被兩個以上的auto_ptr所擁有,
因此,在拷貝構造或賦值操作時,auto_ptr的做法是“所有權轉移”,即拷貝或賦值的源物件將失去對“裸”指標的所有權,
- 這種方法雖然避免了第一個問題,析構的時候不會出現一個指標析構時發現物件已經被析構的問題,
- 但是一個auto_ptr被拷貝或被賦值后,其已經失去對原物件的所有權,如果再對這個指標進行操作則是不安全的,
如下:
int*p = new int(0);
auto_ptr<int>ap1(p);
auto_ptr<int>ap2 = ap1;
cout << *ap1;
此時ap1已經失去了p的使用權,因此就會出現錯誤,
這種情況較為隱蔽的情形出現在將auto_ptr作為函式引數按值傳遞,因為在函式呼叫程序中在函式的作用域中會產生一個區域物件來接收傳入的auto_ptr(拷貝構造).
如下:
void show(auto_ptr<int>ap)
{cout << *ap;
}int main()
{int*p = new int(0);
auto_ptr<int>ap1(p);
show(ap1);
cout << *ap1;
此時ap1已經失去了所有權,所以也會錯誤,
第二個問題:
避免進行拷貝構造與賦值發生錯誤,
auto_ptr常用的成員函式
1) get()

- 第一行與第三行相同,都是int所在的那塊記憶體的地址,
- 第二行是ap1這個類物件本身所在記憶體的地址,
2) reset()
重新設定auto_ptr指向的物件,
類似于賦值操作,但賦值操作不允許將一個普通指標指直接賦給auto_ptr,而reset()允許,如下例:
auto_ptr<int> a(new int(1));
a.reset(new int(2));
在例子中,重置前a擁有“ 1 ”記憶體的所有權,這塊記憶體首先會被釋放,之后a再擁有" 2 "字符記憶體的所有權,
3) release()
回傳auto_ptr指向的那個物件的記憶體地址,并釋放對這個物件的所有權,
用此函式初始化auto_ptr時可以避免兩個auto_ptr物件擁有同一個物件的情況(與get函式相比),
例子如下:
{
auto_ptr<int> a(new int(1));
auto_ptr<int> b(a.release());
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/258780.html
標籤:其他
