/*...更多的代碼...*/
delete pt;
}
我們大多數(shù)人每天寫類似的代碼。如果f()函數(shù)只有三行并且不會(huì)有任何意外,這么做可能挺好的。但是如果f()從不執(zhí)行delete語(yǔ)句,或者是由于過(guò)早的返回,或者是由于執(zhí)行函數(shù)體時(shí)拋出了異常,那么這個(gè)被分配的對(duì)象就沒(méi)有被刪除,從而我們產(chǎn)生了一個(gè)經(jīng)典的內(nèi)存泄漏。
能讓示例1(a)安全的簡(jiǎn)單辦法是把指針?lè)庋b在一個(gè)“智能的”類似于指針的對(duì)象里,這個(gè)對(duì)象擁有這個(gè)指針并且能在析構(gòu)時(shí)自動(dòng)刪除這個(gè)指針?biāo)傅膶?duì)象。因?yàn)檫@個(gè)智能指針可以簡(jiǎn)單的當(dāng)成一個(gè)自動(dòng)的對(duì)象(這就是說(shuō),它出了作用域時(shí)會(huì)自動(dòng)毀滅),所以很自然的把它稱之為“智能”指針:
// 示例 1(b): 安全代碼, 使用了auto_ptr
//
void f()
{
auto_ptr<T> pt( new T );
/*...更多的代碼...*/
} // 酷: 當(dāng)pt出了作用域時(shí)析構(gòu)函數(shù)被調(diào)用,
// 從而對(duì)象被自動(dòng)刪除
現(xiàn)在代碼不會(huì)泄漏T類型的對(duì)象,不管這個(gè)函數(shù)是正常退出還是拋出了異常,因?yàn)閜t的析構(gòu)函數(shù)總是會(huì)在出棧時(shí)被調(diào)用。清理會(huì)自動(dòng)進(jìn)行。
最后,使用一個(gè)auto_ptr就像使用一個(gè)內(nèi)建的指針一樣容易,而且如果想要“撤銷”資源,重新采用手動(dòng)的所有權(quán),我們只要調(diào)用release():
// 示例 2: 使用一個(gè) auto_ptr
//
void g()
{
T* pt1 = new T;
// 現(xiàn)在,我們有了一個(gè)分配好的對(duì)象
// 將所有權(quán)傳給了一個(gè)auto_ptr對(duì)象
auto_ptr<T> pt2( pt1 );
// 使用auto_ptr就像我們以前使用簡(jiǎn)單指針一樣
*pt2 = 12; // 就像 "*pt1 = 12;"
pt2->SomeFunc(); // 就像 "pt1->SomeFunc();"
// 用get()來(lái)獲得指針的值
assert( pt1 == pt2.get() );
// 用release()來(lái)撤銷所有權(quán)
T* pt3 = pt2.release();
// 自己刪除這個(gè)對(duì)象,因?yàn)楝F(xiàn)在
// 沒(méi)有任何auto_ptr擁有這個(gè)對(duì)象
delete pt3;
} // pt2不再擁有任何指針,所以不要
// 試圖刪除它...ok,不要重復(fù)刪除
最后,我們可以使用auto_ptr的reset()函數(shù)來(lái)重置auto_ptr使之擁有另一個(gè)對(duì)象。如果這個(gè)auto_ptr已經(jīng)擁有了一個(gè)對(duì)象,那么,它會(huì)先刪除已經(jīng)擁有的對(duì)象,因此調(diào)用reset()就如同銷毀這個(gè)auto_ptr,然后新建一個(gè)并擁有一個(gè)新對(duì)象:
// 示例 3: 使用reset()
//
void h()
{
auto_ptr<T> pt( new T(1) );
pt.reset( new T(2) );
// 刪除由"new T(1)"分配出來(lái)的第一個(gè)T
} // 最后,pt出了作用域,
// 第二個(gè)T也被刪除了
PS:再貼一個(gè)
http://cns_tech.blogbus.com/logs/4628846.html
#include
#include
#include
using namespace std;
int main(int argc, char* argv[])
{
auto_ptr api ,api2;
api = auto_ptr( new int(10) );
cout<<"api:"<<*api<<endl;
/*
api對(duì)象的布局:
一個(gè)int數(shù)表示該對(duì)象是否有效。(==1有效,==0無(wú)效)
一個(gè)指針 指向int數(shù)據(jù)(因?yàn)槟阍诼暶鱝pi時(shí)已經(jīng)說(shuō)了它時(shí)指向int的)
*/
api2 = api; //傳遞性:執(zhí)行完本句之后,api無(wú)效,同時(shí)api2有效,api2的另一個(gè)字段指向int
auto_ptr aps1,aps2;
aps1 = auto_ptr(new string("pig") );
cout<<"aps1:"<<*aps1<
return 0;
}
vc6的說(shuō)明:auto_ptr
template class auto_ptr
{
public:
typedef T element_type;
explicit auto_ptr(T *p = 0) throw();
auto_ptr(const auto_ptr& rhs) throw();
auto_ptr& operator=(auto_ptr& rhs) throw();
~auto_ptr();
T& operator*() const throw();
T *operator->() const throw();
T *get() const throw();
T *release() const throw();
};
The class describes an object that stores a pointer to an allocated object of type T. The stored pointer must either be null or designate an object allocated by a new expression. The object also stores an ownership indicator. An object constructed with a non-null pointer owns the pointer. It transfers ownership if its stored value is assigned to another object. The destructor for auto_ptr deletes the allocated object if it owns it. Hence, an object of class auto_ptr ensures that an allocated object is automatically deleted when control leaves a block, even via a thrown exception.
//好了,估計(jì)說(shuō)了這么多 ,應(yīng)該知道 auto_ptr的功能和不足了。
//再看看以下我轉(zhuǎn)過(guò)來(lái)的文章
STL中的auto_ptr指針是為了解決內(nèi)存泄漏問(wèn)題而設(shè)計(jì)的。它嚴(yán)格限制了指針擁有對(duì)指向?qū)ο蟮乃袡?quán)。auto_ptr指針和普通指針的差別在于對(duì)指向?qū)ο笏袡?quán)的處理不同。auto_ptr指針是“傳遞”所有權(quán),而普通指針是“共享”所有權(quán)??聪旅胬樱?br>std::auto_ptr p1(new int(24));
std::auto_ptr p2;
int *q1 = new int(12);
int *q2;
p2 = p1;
q2 = q1;
經(jīng)過(guò)兩次賦值后,對(duì)于auto_ptr,p1為NULL,*p2為24;對(duì)于普通指針,*p1, *p2均為12。第一次賦值,p1把指向?qū)ο蟮乃袡?quán)傳遞給了p2, p1不再擁有指向?qū)ο蟮乃袡?quán)。而第二次賦值,q2和q1共享了對(duì)同一對(duì)象的所有權(quán)。因此,對(duì)于auto_ptr,一個(gè)對(duì)象只可能被一個(gè)智能指針指向,這樣可有效避免內(nèi)存泄漏問(wèn)題。但是同時(shí)會(huì)引起新問(wèn)題??聪旅胬樱?br>template
void BadPrint(std::auto_ptr p)
{
if (p.get() == NULL)
{
std::cout<
}
else
{
std::cout<<*p;
}
}
然后我如下使用BadPrint函數(shù):
std::auto_ptr q(new int(18));
BadPrint(q);
*q = 12;
該程序并未像我們所期望的一樣:*q的值為12,而是會(huì)出現(xiàn)runtime error,why?因?yàn)槲覀儼裶作為函數(shù)參數(shù)傳給了BadPrint,因此傳遞完成后q不再擁有對(duì)指向?qū)ο蟮乃袡?quán),而函數(shù)內(nèi)部的局部變量p會(huì)接管q所指向?qū)ο蟮乃袡?quán),當(dāng)函數(shù)執(zhí)行完畢退出時(shí),p的生命期截止同時(shí)delete所指向?qū)ο?。因此q實(shí)際變?yōu)镹ULL,所以出錯(cuò)。如何避免出錯(cuò)?使用auto_ptr的引用?即 void BadPrint(std::auto_ptr &p)。這是相當(dāng)糟糕的一種做法。對(duì)智能指針使用引用混淆了所有權(quán)的問(wèn)題。它導(dǎo)致所有權(quán)有可能被傳遞了,也可能沒(méi)有被傳遞。無(wú)論如何應(yīng)當(dāng)避免對(duì)auto_ptr使用引用。
可見(jiàn)智能指針并非對(duì)任何情況都智能。使用auto_ptr要知道:
1. 智能指針不能共享指向?qū)ο蟮乃袡?quán)
2. 智能指針不能指向數(shù)組。因?yàn)槠鋵?shí)現(xiàn)中調(diào)用的是delete而非delete[]
3. 智能指針不是萬(wàn)能的
4. 智能指針不能作為容器類的元素。
例如:
template
void container::insert(const T &value)
{
..........
X = value;
..........
}
事實(shí)上在stl中,所有的container要內(nèi)部拷貝所傳參數(shù)的值時(shí)都是傳的const類型的值。因此無(wú)法用auto_ptr傳進(jìn)去。
假定有一個(gè)動(dòng)態(tài)分配的int空間,則在一個(gè)時(shí)刻只能有一個(gè)auto_ptr指針指向他!這就是所有權(quán)的獨(dú)占性。
聯(lián)系客服