前言:
c++ stl 標準程序庫提供了一種智能指針,幫助程序員防止"被異常拋出時發生資源泄露"
本篇只講述 auto_ptr ,根據 c++ 標準庫一書總結
void f()
{
classA *p = new classA();
...
delete p;
}
如果我們忘記delete p 釋放資源那麼會造成內存泄露,
就算寫了 delete p
如果在函數體內 return 了,那麼delete 沒執行又泄露了
如果又有異常捕獲呢
void f()
{
classA *p = new classA();
try{
...
}
catch(...){
delete p;
throw;
}
...
delete p;
}
這纔是一個指針p 如果10個呢 那寫起來是不是很麻煩,而且還會造成代碼的複雜和累贅,
這不是優良的編程風格要儘量避免
如果是智能指針,情形就會大不相同
無論在任何情況下,只要自己被摧毀,就一定連帶釋放其所指向的資源,auto_ptr 就是這種智能型指針.
#include <memory>
void f()
{
std::auto_ptr<classA> p(new classA);
}
ok 這樣函數就不用擔心忘記delete 或者return catch 了
注意一點:
auto_ptr 不允許使用一般指針的賦值方式初始化,不允許隱式轉換 explicit
std::auto_ptr<classA> p(new classA); //正確
std::auto_ptr<classA> p = new classA; //錯誤
auto_ptr 擁有嚴格的擁有權觀念,不能出現多個同時擁有多個對象的狀態,
也就是說 一個男人只能取一個老婆,不能同時多個男人同時取一個老婆,
那將會出亂子。auto_ptr 也是這樣,編譯器不會報錯,但是程序員要防範
這種錯誤.
std::auto_ptr<classA> p(new classA);
std::auto_ptr<classA> p2(p);
這時候 p 就把對象的擁有權交給p2了,這時的p是null 在使用它可能會造成意想不到的後果
std::auto_ptr<classA> p(new classA);
std::auto_ptr<classA> p2;
p2 = p;
賦值和上面的結果一樣,p的擁有權交給了p2,通俗講 p與老婆離婚了,他老婆跟了p2,這時的p也就是光棍null了,沒有對象了
如果auto_ptr 以 傳值(by value)的方式傳遞給某函數,那麼他的擁有權也交給了函數的形參
void f(std::auto_ptr<classA> t)
{
...
}
std::auto_ptr<classA> p(new classA);
f(p);
// 這時的 p 就是 null 了,在使用就會出現意想不到的問題
你可能認爲傳引用方式就萬事大吉了,然而這種方式更使擁有權捉摸不定,透過引用來獲得auto_ptr的函數,你根本無法預知擁有權是否被轉移,按引用傳遞auto_ptr是非常糟糕的設計,要全力避免
考慮到auto_ptr 的概念,我們可以運用 const &
這樣的話擁有權就不會發生改變了
void f(const auto_ptr<class A>& p)
{
....
}
std::auto_ptr <classA> p(new classA);
f(p);
//p還可以使用,他的擁有權還有,const 修飾
如果是函數返回值傳遞的話,擁有權就轉移到函數調用端了
std::auto_ptr<classA> f()
{
std::auto_ptr<classA> p(new classA);
...
return p;
}
code:
// testSTL_auto_ptr.cpp : 此文件包含 "main" 函數。程序執行將在此處開始並結束。
//
#include <iostream>
#include <memory>
template <class T>
std::ostream& operator<<(std::ostream& stream, const std::auto_ptr<T>& p)
{
if (p.get() == NULL)
{
stream << "NULL";
}
else
{
stream << *p;
}
return stream;
}
int main()
{
std::auto_ptr<int> p(new int(42));
std::auto_ptr<int> q;
std::cout << "after initialization:" << std::endl;
std::cout << " p:" << p << std::endl;
std::cout << " q:" << q << std::endl;
q = p;
std::cout << "after assigning auto pointers:" << std::endl;
std::cout << " p:" << p << std::endl;
std::cout << " q:" << q << std::endl;
*q += 13;
p = q;
std::cout << "after change and reassignment:" << std::endl;
std::cout << " p:" << p << std::endl;
std::cout << " q:" << q << std::endl;
system("pause");
}
運行結果:
after initialization:
p:42
q:NULL
after assigning auto pointers:
p:NULL
q:42
after change and reassignment:
p:55
q:NULL
注意:
std::ostream& operator<<(std::ostream& stream, const std::auto_ptr& p)
這個重載第二個參數是 const reference 所以不會發生擁有權的轉移