【C+++-30】C++aut_ptrスマートポインタの使い方
記事の転載先: http://blog.csdn.net/monkey_d_meng/articale/detail/5901392
C++の中のポインターアプリケーションとリリースメモリは、通常、newとdeleteという方式を採用しています.しかし、標準C++の中にもう一つの強力なモデルがあります.ptr、使わない時に自動的にメモリを解放してくれます.使い方を簡単に説明します.
:
std::auto_ptrm_example(new T());
:
std::auto_ptrm_example;
m_example.reset(new T());
( ):
std::auto_ptrm_example1(new T);
std::auto_ptrm_example2(new T);
m_example2=m_example1;
C++はm(u)を返しますexampleが指すメモリを回収し、m_example 1 の値はNULLですので、C++の中では、aut_は絶対に避けてください.ptrは容器に入れます.下記のコードを避けるべきです.
vector>m_example;
アルゴリズムで容器を操作すると、STL内部で容器中の要素の割り当てが行われるのを避けることができません.このようにすると、容器中の複数の要素がNULLに配置されます.ptrスマートポインタはvectorに置いてはいけません.
ただし、標準のautptrスマートポインター機構は多くの人が知っていますが、あまり使いません.これは本当に残念です.ptrは優雅にC+++設計と符号化によくある問題を解決し、適切に使用すれば丈夫なコードを生成することができる.本稿では、atot_をどのように正しく使うかを述べた.ptrはあなたのコードをより安全にします.また、aut_を避けるにはどうすればいいですか?ptr危険ですが、よくある誤用で、これらの誤用は中断的な発作を引き起こし、診断しにくいbugを引き起こします.
autoptrがしていることは、動的に対象を割り振ることと、対象が必要でないときに自動的にクリーンアップを実行することです.ここでは簡単なコード例ですが、aut_は使用されていません.ptrですので、安全ではありません.
// 1(a):
void f()
{
T* pt( new T );
/*... ...*/
delete pt;
}
ほとんどの人が毎日同じようなコードを書きます.f()関数が3行しかないなら、何の意外もないです.それはいいかもしれません.しかし、f()がdelete文を実行しない、あるいは早すぎる戻り、あるいは関数体を実行する時に異常を投げた場合、この割り当てられた対象は削除されず、古典的なメモリ漏れが発生しました.
例1(a)を安全にすることができる簡単な方法は、ポインタをポインタのようなオブジェクトにパッケージすることであり、このオブジェクトはこのポインタを有しており、解析時にこのポインタが指すオブジェクトを自動的に削除することができる.このスマートポインターは自動的なオブジェクトとして簡単に使えますので、自然にスマートポインターと呼ばれています.
// 1(b): , auto_ptr
void f()
{
auto_ptr pt( new T );
/*... ...*/
} // : pt ,
現在のコードはTタイプのオブジェクトが漏れません.この関数が正常に終了しても、例外が出ても、ptのコンストラクターは常にスタックを出る時に呼び出されます.掃除は自動的に行われます.
最後に、autを使います.ptrはビルドされたポインタを使用するように簡単で、リソースをキャンセルしたいなら、手動の所有権を再採用します.release()を呼び出すだけです.
// 2: auto_ptr
void g()
{
// ,
T* pt1 = new T;
// auto_ptr
auto_ptr pt2(pt1);
// auto_ptr ,
*pt2 = 12; // *pt1 = 12
pt2->SomeFunc(); // pt1->SomeFunc();
// get()
assert( pt1 == pt2.get() );
// release()
T* pt3 = pt2.release(); //
// , auto_ptr
delete pt3;
} // pt2 , ...OK,
最後に、私達はaut_を使うことができます.ptrのreset()関数はaut_をリセットします.ptrは別のオブジェクトを持たせる.もしこのautがptrはオブジェクトを持っていますが、先に所有しているオブジェクトを削除しますので、このautを破壊するようにreetを呼び出します.ptrを新規作成し、新しいオブジェクトを所有します.// 3: reset()
void h()
{
auto_ptr pt( new T(1) );
pt.reset( new T(2) ); // "new T(1)" T
} // pt , T
autoptr使い方:
1. ヘッダファイルが必要です.
2.コンストラクタ:explicit atotptr(X*p=0)throw()//ポインタpをatotに渡す.ptr対象委託管理
3.Copy constructor:atotptr(const atooth&)throw();template atotptr(const atooth&a)throw()//指針の信託統治権が移転します.
4.Destructor:~aut_ptr()//ポインタpが指す空間を解放します.
5. 二つのメンバー関数を提供します. X*get()const throw(); //保存されたポインタを返します.
6. オブジェクトにまだポインタが残っています. X*release()const throw(); //保存されたポインタを返します.オブジェクトにはポインタが保存されていません.
autoptr実現のポイント:
1. 特徴「スタック上のオブジェクトは、作用範囲から離れると自動的に分析される」.
2. 動的に割り当てられたメモリに対しては、その役割範囲はプログラマが手動で制御しています.これはプログラマに便利さをもたらしましたが、メモリの漏れも避けられません.コンパイラだけが最も信頼できるものです.
3.aut_ptrはスタック上にオブジェクトaを構築することにより、オブジェクトaにおけるwrapはメモリを動的に割り当てるポインタpを有し、ポインタpに対する操作はすべて対象aの動作に移行する.aのコンストラクタではpの空間が自動的に解放されますが、このコンストラクタはコンパイラが自動的に起動します.プログラマが心配する必要はありません.
多く言っても無駄です.一番実用的な例を見てください.
#include
#include
using namespace std;
class TC
{
public:
TC(){cout< pTC(new TC); // 2
//TC *pTC = new TC; // 1
try
{
if(isThrow)
throw "haha";
}
catch(const char* e)
{
//delete pTC; // 1
throw;
}
//delete pTC; // 1
}
int main()
{
try
{
foo(true);
}
catch(...)
{
cout<
1.シナリオ1を採用するなら、関数がthrow異常の時に割り当てられたメモリを解放することを考慮しなければならない.これによって、各分岐において、注意深く手動で行うことになる. delete pTC
2.方案2を採用するなら、いつメモリを解放するか心配しなくてもいいです.foo()がどういう理由で退出するかに関わらず、スタック上のオブジェクトpTCのコンフィギュレーション関数は全部呼び出されます.そのため、中にあるポインタが指すメモリは必ず安全に解放されます.
しかし、使用中の落とし穴の一つに注意してください.それは指針の信託統治権が移転します.例えば上記の例では、 autoptr pTC(new TC) autoptr pTC 1=pTC pTC 1はポインタを持ち、pTCがなくなったら、pTCで参照するとメモリエラーが発生します.
この問題を避けるためには、参照カウントを採用したスマートポインタを使用することが考えられます.ptrなど.autoptrはプログラムの効率を下げることはできませんが、aut_ptrは配列には適用されません.aut_ptrは大規模に使ってはいけません. shared_ptrもweaked(u)に合わせてptrは、循環参照をトリガしやすく、メモリを永遠に回収できません.
理論的には、コンテナを合理的に使用してスマートポインタを追加し、C++はメモリリークを完全に避けることができます.