生のポインタは、スタックまたはヒープに割り当てられたオブジェクトを指すことができます。
ヒープ割り当ての例:
// heap allocation
int* rawPtr = new int(100);
std::cout << *rawPtr << std::endl; // 100
スタック割り当ての例:
int i = 100;
int* rawPtr = &i;
std::cout << *rawPtr << std::endl; // 100
Auto_ptrの例を使用したヒープ割り当て:
int* rawPtr = new int(100);
std::unique_ptr<int> uPtr(rawPtr);
std::cout << *uPtr << std::endl; // 100
Auto_ptrの例を使用したスタック割り当て:
int i = 100;
int* rawPtr = &i;
std::unique_ptr<int> uPtr(rawPtr); // runtime error
「スマートポインタ」は、ヒープ上に動的に作成されたオブジェクトを指すために使用されることを意図していますか? C++ 11の場合、スタックに割り当てられたオブジェクトを指すために生のポインターを引き続き使用することになっていますか?ありがとうございました。
スマートポインタは通常、new
で割り当てられ、delete
で削除されたオブジェクトを指すために使用されます。これらをこのように使用する必要はありませんが、言語構造の使用目的を推測したい場合は、それが目的のようです。
最後の例でコードがクラッシュする理由は、「deleted with delete
」の部分が原因です。スコープ外になると、unique_ptrはポインタを持つオブジェクトをdelete
しようとします。スタックに割り当てられているため、これは失敗します。あなたが書いたかのように、_delete rawPtr;
_
通常、ヒープオブジェクトでスマートポインタを使用するため、ヒープに割り当てて、一度にスマートポインタに変換する関数があります。 std::unique_ptr<int> uPtr = make_unique<int>(100);
は、3番目の例の最初の2行のアクションを実行します。共有ポインタに一致する_make_shared
_もあります。
スタックオブジェクトでスマートポインタを使用することが可能です。スマートポインターが使用する削除プログラムを指定し、delete
を呼び出さない削除プログラムを提供します。これはスタック変数であり、削除するために何もする必要がないため、削除者は何もできません。何もしない関数を呼び出すだけなら、スマートポインタのポイントは何でしょうか。これが、スタックオブジェクトで使用されるスマートポインタが一般的に見られない理由です。しかし、ここにいくつかの有用性を示す例があります。
_{
char buf[32];
auto erase_buf = [](char *p) { memset(p, 0, sizeof(buf)); };
std::unique_ptr<char, decltype(erase_buf)> passwd(buf, erase_buf);
get_password(passwd.get());
check_password(passwd.get());
}
// The deleter will get called since passwd has gone out of scope.
// This will erase the memory in buf so that the password doesn't live
// on the stack any longer than it needs to. This also works for
// exceptions! Placing memset() at the end wouldn't catch that.
_
ランタイムエラーは、delete
が割り当てられなかったメモリ位置でnew
が呼び出されたことが原因です。
オブジェクトがすでに 動的ストレージ期間 (通常は「ヒープ」での作成として実装されている)で作成されている場合、「スマートポインタ」はランタイムエラーで示されるように正しく動作しません。
「スマートポインタ」は、ヒープ上に動的に作成されたオブジェクトを指すために使用されることを意図していますか? C++ 11の場合、スタックに割り当てられたオブジェクトを指すために生のポインターを引き続き使用することになっていますか?
何をすべきかについては、保存期間、具体的にはオブジェクトがどのように作成されたかを考えると役立ちます。
したがって、最後の例では、次の方が適切です(ポインターはintを所有します)。
auto uPtr = std::make_unique<int>(100);
uPtr
には自動保存期間があり、スコープ外になるとデストラクタが呼び出されます。 int
には動的なストレージ期間(ヒープ)があり、スマートポインターによってdelete
されます。
一般に、new
とdelete
の使用を避け、生のポインターの使用を避けることができます。 make_unique
およびmake_shared
、new
は必要ありません。
「スマートポインタ」は、ヒープ上に動的に作成されたオブジェクトを指すために使用されることを意図していますか?
これらは、リークを防ぐためにヒープに割り当てられたオブジェクトを対象としています。
C++のガイドラインは、単一のオブジェクトへの参照へのプレーンポインタを使用することです(ただし、オブジェクトを所有していません)。オブジェクトのownerは、値によって、コンテナー内に、またはスマートポインターを介してオブジェクトを保持します。
「スマートポインタ」は、ヒープ上に動的に作成されたオブジェクトを指すために使用されることを意図していますか?
はい、しかしそれはただのデフォルトです。 std::unique_ptr
には コンストラクター (そのページには(3)/(4)はありません)があり、あなたが取得したポインターを受け取ることに注意してください。どういうわけか、そしてあなたが提供する「削除者」。この場合、一意のポインタはヒープに対して何もしません(削除者がそうしない限り)。
C++ 11の場合、スタックに割り当てられたオブジェクトを指すために生のポインターを引き続き使用することになっていますか?ありがとうございました。
ポインタを「所有」しないコードでは、生のポインタを使用する必要があります。割り当てや割り当て解除に関係する必要はありません。それは、ヒープ、スタック、または他の場所を指しているかどうかに関係ありません。
これを使用するもう1つの場所は、保護された/プライベートメンバーのために、複雑な所有権パターンを持つクラスを実装する場合です。
PS:お願いします、std::auto_ptr
を忘れてください...存在しなかったふりをしてください:-)