STLのスマートポインタ(std::unique_ptr
)のget
メンバー関数がT* get() const
と戻り値にconst
が存在しないことに悩んでいましたが、以下の質問サイトの回答を読んで腑に落ちました。スマートポインタの指す値をconst
にするにはT
をconst T
とするようです。
上記の回答と実際のコードをあわせて考えると以下のようです。「○」はコンパイル可能、「×」はコンパイルエラーを表しています。
生ポインタ | スマートポインタ | t = ... |
*t = ... (*t.get() = ... ) |
---|---|---|---|
T* t |
std::unique_ptr<T> t |
○ | ○ |
const T* t |
std::unique_ptr<const T> t |
○ | × |
T* const t |
const std::unique_ptr<T> t |
× | ○ |
const T* const t |
const std::unique_ptr<const T> t |
× | × |
std::unique_ptr<const T> p
はconst T* p
のように振る舞う。const std::unique_ptr<const T> p
はconst T* const p
のように振る舞う。const std::unique_ptr<T> p
はT* const p
のように振る舞う。
STLスマートポインタのconst修飾確認用コード
#include <memory> #include <string> int main() { auto p1 = std::make_unique<const int>(123); p1 = nullptr; *p1.get() = 456; // コンパイルエラー。p1の指す値はconst。 const auto p2 = std::make_unique<int>(123); p2 = nullptr; // コンパイルエラー。p2自体の値はconst。 *p2.get() = 456; const auto p3 = std::make_unique<const int>(123); p3 = nullptr; // コンパイルエラー。p3自体の値はconst。 *p3.get() = 456; // コンパイルエラー。p3の指す値はconst。 return 0; }
生ポインタのconst修飾確認用コード
int main() { int x = 123; const int* p1 = &x; // int const* p1...でも同様。 p1 = nullptr; *p1 = 456; // コンパイルエラー。p1の指す値はconst。 int* const p2 = &x; p2 = nullptr; // コンパイルエラー。p2自体の値はconst。 *p2 = 456; const int* const p3 = &x; // int const* const p1...でも同様。 p3 = nullptr; // コンパイルエラー。p3自体の値はconst。 *p3 = 456; // コンパイルエラー。p3の指す値はconst。 return 0; }
補足
- メンバー関数の引数リストの後にある
const
(T member_fn(...) const
)はフィールドの値自体の不変だけを要求します。get
の戻り値を間接参照*
で変更してもスマートポインタの管理するフィールドは変化しないので、この仕様は満たされています。