次のようなクラスがあるとします。
class DoStuffWithRef
{
DoStuffWithRef(LargeObject& lo) : lo_(lo) {}
// a bunch of member functions, some of them useful
// [...]
private:
LargeObject& lo_;
};
このクラスは、少なくとも 1 つの他のエンティティがlo_
参照するオブジェクトの所有権を持っている場合にのみ適切な使用ができるように設計されています。クライアント コードでクラスが適切に使用されている場合、 が のDoStuffWithRef
所有権を持つ必要はありませんLargeObject
。
クラスが誤用されている場合、この使用法を強制したり、エラーを通知したりする方法はありますか? の使用目的を文書化する以外に何かできることはありDoStuffWithRef
ますか?
たとえば、自動的に保存されDoStuffWithRef
た は、自動的に保存された を参照する場合がありますLargeObject
。
void foo()
{
LargeObject lo;
DoStuffWithRef dswr(lo);
// some code that makes use of the DoStuffWithRef instance
return;
}
これは私が念頭に置いている主な使用法ですが、他の誰かが所有権を持つことが保証されている可能性がある他のケースもあります。
DoStuffWithRef
問題は、クライアント コードがダングリング リファレンスで終わるインスタンスを作成する可能性が非常に高いことです。LargeObject
が参照するの所有者が他にいない場合、 がにアクセスしようとするとDoStuffWithRef
混乱が生じます。さらに悪いことに、エラーが発生してからしばらくして混乱が生じる可能性があります。DoStuffWithRef
LargeObject
これが過去に出てきたとき、私はboost::shared_ptr<>
参照の代わりに a を使用しました (これは C++03 でした)。それは、クラスのセマンティクスを適切に表現していません。前提は、DoStuffWithRef
所有権を必要としないということです。それは、他の人が所有するオブジェクトに作用することを意図しており、他の誰もオブジェクトを所有していない場合、によって提供される機能はDoStuffWithRef
意味がありません。に所有権を与えるDoStuffWithRef
と、不要なオーバーヘッドが発生し、共有所有権のセマンティクスが強制されます。weak_ptr<>
ポインターが有効かどうかを実行時に確認するべきではないため、セマンティクスも間違っています。
コードのパフォーマンスに敏感なセクションや、所有権の共有が大きな負担になるケースでこのシナリオが発生したことは一度もないので、実際には問題にはなりませんでしたが、これを C++ で正確に表現する方法を知っていればよかったと思います。費用はわずかですが、不必要でもあります。さらに重要なshared_ptr<>
ことは、クラスの誤った使用を隠すことです。を使用するDoStuffWithRef
ように変更されたshared_ptr<>
が の残りの唯一の所有者であるLargeObject
場合、ダングリング リファレンスは短期的に回避されますが、クライアント コードは未知の領域に行き着きます。