C ++スマートポインターテンプレート
動的メモリ割り当ての管理に役立つ
ヒープメモリを含む動的メモリ割り当てが含まれる場合、常に削除を覚えておく必要がありますが、間違いを犯して忘れてメモリリークを引き起こすことが常にあります。
これを忘れなくても、例外によって破棄される可能性があります。
以下の関数がある場合は、関数内で動的メモリを要求し、終了時に削除してください。問題は次のとおりです。例外が発生した場合のメモリリーク。スタックアンワインドの原理を知っている場合は、pポインタメモリは解放されますが、ポイントされたメモリは解放されません
。スタックアンワインドに関するいくつかの紹介。
リンク:https://blog.csdn.net / Valishment / article / details / 104962230。
void GetInt(int* p)
{
p = new int;
...
if (one_error())
throw();
...
delete p;
return;
}
ポインタが自動変数ではなく自動オブジェクトである場合、スタックがアンタイされたときに自動オブジェクトのデストラクタが呼び出され、それによってポイントされたメモリ領域が削除されます。
次の3つのポインタはまさにそれを行います。
ヘッダーファイル(メモリ)内
テンプレート1.auto_ptrテンプレートクラス(C ++ 98)------- C ++ 11が放棄されました
double* p0 = new double;
std::auto_ptr<double> p1(new double);
// p1 为double* 类型
//std::auto_ptr<double*> p1(new double); 错误
// p2 为double**类型
p1 = auto_ptr<double>(p0);
//这种显示转换对三种指针都有效
std::auto_ptr<Student> p2(new Student("小明", 12, "Grade 5"));
Doubleはビルトインタイプ、Studentはカスタムタイプです。
ヒープメモリも指すポインタを表示できます。
問題:
2つのスマートポインタが同じ領域を指しているため、同じ領域が処理されずに複数回削除されます。
std::auto_ptr<double> p1(new double);
*p1 = 10;
std::auto_ptr<double> p2 = p1;
std::cout << *p1 << *p2 << std::endl;
std::auto_ptr<double> p3;
p3 = p2;
std::cout << *p2 << *p3 << std::endl;
// p1: 我没了啊(NULL)
// p2: 内存归我了(000XXXXX)
std::auto_ptr<double> p3;
p3 = p2;
std::cout << *p2 << *p3 << std::endl;
// p2: 我怎么也没了??(NULL)
// p3: 现在归我了!!(000XXXXX)
// ....
// ....
auto_ptrテンプレートがこのようなイベントを処理すると、前のポインターがnullポインターに変わります。つまり、右辺値ポインターがNULL
になります。ここで、右辺値はp1とp2です。左辺値は変更された値、つまりp2、p3です。
したがって、これは危険です。C++ 11はそれを放棄し、NULLポインタを出力するときにプログラムがクラッシュすることを誰も望んでいません。
テンプレート2.unique_ptrテンプレートクラス(優秀な学生)
このテンプレートの使用は、auto_ptrテンプレートと同じです。
上記に続いて、unique_ptrはそのようなイベントを処理するときに相互割り当てを禁止します
...
p2 = p1;
// 编译器说:我不同意
...
p2 = p3
// p1:活下来了
例外:
ヒープメモリをスマートポインタに割り当てるように特別に要求し、それを戻り値として返す関数を作成するとします。(戻るときに自動変数が破棄されるため、つまり、関数内のスマートポインターが自動的に消え、出力NULLポインターがなくなります)
unique_ptr<...> GetHeap()
{
...
unique_ptr<...> p = new ..;
// 快要被干掉的指针p
// 要找个家伙继承下财产
...
return p;
}
unique_ptr<...> ptr1 = GetHeap();
// ptr1继承了p的遗产(允许)
これはコードで行われ、コンパイラは他のポインタへのこの種の生命のないスマートポインタのみを許可します。
テンプレート3.shared_ptrクラステンプレート(よりインテリジェント)
ポインタが割り当てられると、カウントは+1(静的静的型変数)になり、最後のポインタが削除されようとすると、ポイントされているメモリ領域が解放されます。
つまり、この種のポインタでは、複数のポインタが同じヒープメモリを指すことができますが、解放するのは1回だけです。
注意!
スマートポインタを初期化するときは、ヒープメモリ領域のアドレスのみを使用できます。!!
1.新しい割り当てを使用する場合、これら3つのポインターテンプレート
auto_ptrおよびshared_ptrのデストラクターはdeleteです!!! delete []ではありません!!!
したがって、new []を使用してauto_ptrおよびshared_ptrポインターを初期化することはできません。
unique_ptrは、両方のタイプのnewをサポートします。new
とdeleteはペアになり、new []はdelete []とペアになります。