C++のスマートポインタ
4981 ワード
C++のスマートポインタ
C++の4つのスマートポインタはそれぞれ
1.shared_ptr
2.unique_ptr
3.weak_ptr
4.auto_ptr(c++11によって廃棄された)(c++11の環境でwarning:'auto_ptr'is deprecatedが爆発する)
インテリジェントポインタの役割
インテリジェントポインタの役割は、ポインタを管理することです.
申請されたスペースが関数の終了時に解放され忘れ、メモリが漏洩する場合があるためです.
インテリジェントポインタを使用すると、この問題を大幅に回避できます.インテリジェントポインタはクラスであり、クラスの役割ドメインを超えた場合、クラスは自動的に構造関数を呼び出し、構造関数は自動的にリソースを解放します.したがって、スマートポインタの機能原理は、関数の終了時にメモリ領域を自動的に解放し、手動でメモリ領域を解放する必要がないことです.
インテリジェントポインタの設計思想は簡単に言えば、基本タイプのポインタをクラス(テンプレートクラス)オブジェクトポインタにカプセル化し、構造関数にdelete文を記述してポインタが指すメモリ空間を削除することです.
インテリジェントポインタの使用
スマートポインタが存在するヘッダファイル:#includeスマートポインタにはexplicitコンストラクション関数(明示的コンストラクション関数) があります.
スマートポインタの呼び出しは呼び出しのみ表示されます
eg:
よく間違いを犯す場所:
ここで定義したaはスタックメモリを使用し、ptが期限切れになるとdelete演算子が非スタックメモリに使用されます.これはエラーです. 2 2 2つのポインタが同じオブジェクトを指す問題について、 は、深いレプリケーションを実行するための値付け演算子を定義します.
深いレプリケーションとは:既存のオブジェクトのすべてのメンバー変数を新しいオブジェクトにコピーするだけでなく、新しいオブジェクトにメモリを割り当て、既存のオブジェクトが持つメモリもコピーします.その結果、既存のオブジェクトと新しいオブジェクトが持つダイナミックメモリは互いに独立しており、1つのオブジェクトのデータを変更しても他のオブジェクトには影響しません.
このような実行の結果はメモリの浪費であり、スマートポインタはこのスキーム を採用していない.所有権概念(auto_ptr、unique_ptr)を確立特定のオブジェクトに対して、1つのスマートポインタのみが所有可能であり、これにより特定のオブジェクトを所有するスマートポインタのみがそのオブジェクトを削除することができる.付与操作は所有権の譲渡に等しい. 参照カウント法(shared_ptr)は、特定のオブジェクトのスマートポインタ数を追跡し、付与時にカウント+1、期限切れ時にカウント-1、参照カウントが0に減少した場合にのみdelete を呼び出す.
なぜautoを廃棄したのかptrセキュリティの問題、auto_の使用ptrが不適切でメモリクラッシュを起こしやすいeg:
note: declared here unique_ptr& operator=(const unique_ptr&) = delete;
だからauto_ptrは23333 で廃棄されました unique_ptrの利点は、まず同じ所有権モードのスマートポインタであり、uniqueはポインタの所有権が奪われた後にエラーにアクセスします.次に、get関数に対して返された一時ポインタの所有権がpsポインタに取得された後、一時ポインタが破棄されます.この一時ポインタは無効なデータ、すなわちunique_にアクセスしません.ptr(new Temp(val))は、あるポインタを安全に別のポインタに割り当てるには、c++標準ライブラリのmove関数eg: を使用する一時的な右値として現れる.
スマートポインタの選択
(1)プログラムが同じオブジェクトを指す複数のポインタを使用する場合、shared_ptrを選択します.にはポインタ配列があり、最大の要素と最小の要素などの特定の要素を示すためにいくつかの補助ポインタが使用される. の2つのオブジェクトは、3番目のオブジェクトを指すポインタを含む. STLコンテナにはポインタが含まれています.多くのSTLアルゴリズムでは、shared_に使用できるレプリケーションおよび付与操作がサポートされています.ptrですがunique_には使用できませんptr(コンパイラがwarningを発行)とauto_ptr(動作不確定).コンパイラがshared_ptrを提供していない場合は、Boostライブラリが提供するshared_ptrを使用します. (2)プログラムが同じオブジェクトを指す複数のポインタを必要としない場合、unique_ptrを使用することができる.
関数がnewを使用してメモリを割り当て、そのメモリへのポインタを返す場合は、その戻りタイプをunique_と宣言します.ptrはいい選択です.
これにより、所有権は戻り値を受け入れるunique_に譲渡されるptrは、deleteの呼び出しを担当します.unique_ptrはSTLコンテナに格納され、uniqueを呼び出さない限りptrは、sort()のような別のアルゴリズムをコピーまたは付与する.
unique_でptrが右の値の場合、shared_に割り当てることができます.ptr、これはunique_ptrは、同じ条件を満たす必要があることを与える.
テンプレートshared_ptrには、右のunique_を使用できる明示的な構造関数が含まれています.ptrをshared_に変換ptr.shared_ptrは元のuniqueに引き継ぐptrのすべてのオブジェクト.
eg:
C++の4つのスマートポインタはそれぞれ
1.shared_ptr
2.unique_ptr
3.weak_ptr
4.auto_ptr(c++11によって廃棄された)(c++11の環境でwarning:'auto_ptr'is deprecatedが爆発する)
インテリジェントポインタの役割
インテリジェントポインタの役割は、ポインタを管理することです.
申請されたスペースが関数の終了時に解放され忘れ、メモリが漏洩する場合があるためです.
インテリジェントポインタを使用すると、この問題を大幅に回避できます.インテリジェントポインタはクラスであり、クラスの役割ドメインを超えた場合、クラスは自動的に構造関数を呼び出し、構造関数は自動的にリソースを解放します.したがって、スマートポインタの機能原理は、関数の終了時にメモリ領域を自動的に解放し、手動でメモリ領域を解放する必要がないことです.
インテリジェントポインタの設計思想は簡単に言えば、基本タイプのポインタをクラス(テンプレートクラス)オブジェクトポインタにカプセル化し、構造関数にdelete文を記述してポインタが指すメモリ空間を削除することです.
インテリジェントポインタの使用
スマートポインタが存在するヘッダファイル:#include
templet
class auto_ptr{
explicit auto_ptr(X* p=0);
}
スマートポインタの呼び出しは呼び出しのみ表示されます
eg:
#include
using namespace std;
int main(){
shared_ptr pd;
double *ptr_reg=new double;
pd=shared_ptr(ptr_reg);
shared_ptr pshared(ptr_reg);
}
よく間違いを犯す場所:
#include
using namespace std;
int main(){
int a=5;
shared_ptr pt(&a);
}
ここで定義したaはスタックメモリを使用し、ptが期限切れになるとdelete演算子が非スタックメモリに使用されます.これはエラーです.
#include
using namespace std;
int main(){
auto_ptr ps(new string ("first blood!"));
auto_ptr tmp;
tmp=ps;
}
に2つのポインタが「first blood」というstringオブジェクトを指すと、プログラムはこのstringオブジェクトを2回削除しようとします.よく知られているように、削除されたオブジェクトを指すポインタは野ポインタです.これによりメモリが漏れるため、野ポインタの発生を避けるために、以下の解決策があります.深いレプリケーションとは:既存のオブジェクトのすべてのメンバー変数を新しいオブジェクトにコピーするだけでなく、新しいオブジェクトにメモリを割り当て、既存のオブジェクトが持つメモリもコピーします.その結果、既存のオブジェクトと新しいオブジェクトが持つダイナミックメモリは互いに独立しており、1つのオブジェクトのデータを変更しても他のオブジェクトには影響しません.
このような実行の結果はメモリの浪費であり、スマートポインタはこのスキーム
#include
using namespace std;
int main() {
auto_ptr str[5] = {
auto_ptr(new string("str1")),
auto_ptr(new string("str2")),
auto_ptr(new string("str3")),
auto_ptr(new string("str4")),
auto_ptr(new string("str5")),
};
auto_ptr ps;
ps = str[2];
for(int i = 0; i < 5; i++) {
cout << *str[i] << endl;
}
}
でコード変更を実行するとstr 2に出力するとプログラムが停止します.ここでpsスマートポインタがstr[2]の所有権を持ち、出力時に空のポインタにアクセスするとプログラムがクラッシュしauto_ptrをshared_に変更ptrまたはunique_ptrの場合、プログラムはクラッシュしませんunique_を使用します.ptrの場合、プログラムはエラーを報告します.note: declared here unique_ptr& operator=(const unique_ptr&) = delete;
だからauto_ptrは23333
#include
using namespace std;
unique_ptr get(const char *s) {
unique_ptr tmp(new string(s));
return tmp;
}
int main() {
unique_ptr ps;
ps = get("23333");
cout<
スマートポインタの選択
(1)プログラムが同じオブジェクトを指す複数のポインタを使用する場合、shared_ptrを選択します.
関数がnewを使用してメモリを割り当て、そのメモリへのポインタを返す場合は、その戻りタイプをunique_と宣言します.ptrはいい選択です.
これにより、所有権は戻り値を受け入れるunique_に譲渡されるptrは、deleteの呼び出しを担当します.unique_ptrはSTLコンテナに格納され、uniqueを呼び出さない限りptrは、sort()のような別のアルゴリズムをコピーまたは付与する.
unique_でptrが右の値の場合、shared_に割り当てることができます.ptr、これはunique_ptrは、同じ条件を満たす必要があることを与える.
テンプレートshared_ptrには、右のunique_を使用できる明示的な構造関数が含まれています.ptrをshared_に変換ptr.shared_ptrは元のuniqueに引き継ぐptrのすべてのオブジェクト.
eg:
#include
using namespace std;
unique_ptr get(const char *s) {
unique_ptr tmp(new string(s));
return tmp;
}
int main() {
unique_ptr ps1, ps2;
ps1 = get("str1");
ps2 = move(ps1);
ps1 = get("str2");
cout << *ps2 << " " << *ps1 << endl;
}