boost :: scoped_ptrではoperator*
、operator->
宣言されたconst
関数ですが、これらは戻りT&
、T*
クライアントが基になるデータを変更できる可能性があります。これは論理的恒常性の概念に違反します(Myers、Effective C ++)
const関数にシグネチャが必要ではありませんか?
const T& operator*() const;
const T* operator->() const;
boost :: scoped_ptrではoperator*
、operator->
宣言されたconst
関数ですが、これらは戻りT&
、T*
クライアントが基になるデータを変更できる可能性があります。これは論理的恒常性の概念に違反します(Myers、Effective C ++)
const関数にシグネチャが必要ではありませんか?
const T& operator*() const;
const T* operator->() const;
ここでの基本的な問題は、scoped_ptr
オブジェクトがクラス オブジェクトではなくポインターのように動作することです (scoped_ptr
インスタンスは実際にはクラス オブジェクトですが)。
Boost が提供するスマート ポインター クラスは、参照カウントや (この場合は) RAII セマンティクスなどの追加機能を提供しながら、生のポインター セマンティクスを可能な限り保持するように設計されています†</sup>。
そのために、 のoperator*()
andoperator->()
メンバーはscoped_ptr
、その「constness 動作」が生のポインターの動作と本質的に一致するように記述されています。
「ダム」ポインターでこの状況を考えてみましょう。
// Can change either Foo or ptr.
Foo* ptr;
// Can't change Foo via ptr, although ptr can be changed.
const Foo* ptr;
// Can't change ptr, although Foo can be changed via ptr.
Foo* const ptr;
// Can't change Foo or ptr.
const Foo* const ptr;
アナログは次のscoped_ptr
ようになります。
// Can change either Foo or ptr.
scoped_ptr<Foo> ptr;
// Can't change Foo via ptr, although ptr can be changed.
scoped_ptr<const Foo> ptr;
// Can't change ptr, although Foo can be changed via ptr.
const scoped_ptr<Foo> ptr;
// Can't change Foo or ptr.
const scoped_ptr<const Foo> ptr;
scoped_ptr
実際には未加工のポインタではありませんが、演算子の記述方法により、上記のコード スニペットが可能になります。
いずれの場合も、コードは を逆参照できる必要がありますptr
。演算子を作成することにより、逆参照/メンバー アクセス演算子を sと非s のconst
両方で呼び出すことができます。const
const
scoped_ptr
scoped_ptr<Foo>
ユーザーが a を宣言すると、次のメンバーが含まれることに注意してください。
Foo& operator*() const;
Foo* operator->() const;
ascoped_ptr<const Foo>
には次のメンバーが含まれます。
const Foo& operator*() const;
const Foo* operator->() const;
したがって、ポインターの const-correctness 動作は、実際にはこの方法で保持されます。
†</sup>しかし、それ以上ではありません。
boost::scoped_ptr では、operator* と operator-> は const 関数として宣言されていますが、T& と T* を返すため、クライアントが基になるデータを変更できる可能性があります。
「基になるデータ」は、スマート ポインター値の一部ではありません。2 つの (スマート) ポインターは、同じオブジェクト iff を指している場合は同等a == b
です&*a == &*b
。
これは、論理定数の考え方に違反しています (Myers、Effective C++)
いいえ、違います:
スマート ポインターの論理値は、それが指している対象にのみ依存します。
スマート ポインターを逆参照しても、それが指すものは変わりません。
そのため、スマート ポインターを逆参照しても、その論理値 (または必要に応じてその状態) は変更されません。
QED
Ascoped_ptr<T>
は のようなものT*
です。のようではありませんT* const
。
Ascoped_ptr<T const>
は a のようなものでT const*
(これは と書くことができますconst T*
)、そうして初めて、ものを返すことが期待operator*
されます。operator->
const