0

次のようなクラスがあるとします。

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混乱が生じます。さらに悪いことに、エラーが発生してからしばらくして混乱が生じる可能性があります。DoStuffWithRefLargeObject

これが過去に出てきたとき、私はboost::shared_ptr<>参照の代わりに a を使用しました (これは C++03 でした)。それは、クラスのセマンティクスを適切に表現していません。前提は、DoStuffWithRef所有権を必要としないということです。それは、他の人が所有するオブジェクトに作用することを意図しており、他の誰もオブジェクトを所有していない場合、によって提供される機能はDoStuffWithRef意味がありません。に所有権を与えるDoStuffWithRefと、不要なオーバーヘッドが発生し、共有所有権のセマンティクスが強制されます。weak_ptr<>ポインターが有効かどうかを実行時に確認するべきではないため、セマンティクスも間違っています。

コードのパフォーマンスに敏感なセクションや、所有権の共有が大きな負担になるケースでこのシナリオが発生したことは一度もないので、実際には問題にはなりませんでしたが、これを C++ で正確に表現する方法を知っていればよかったと思います。費用はわずかですが、不必要でもあります。さらに重要なshared_ptr<>ことは、クラスの誤った使用を隠すことです。を使用するDoStuffWithRefように変更されたshared_ptr<>が の残りの唯一の所有者であるLargeObject場合、ダングリング リファレンスは短期的に回避されますが、クライアント コードは未知の領域に行き着きます。

4

1 に答える 1

0

そうでなければ DoStuffWithRef はステートフルですか? そうでない場合は、ユーティリティ関数のバケツのようです。LargeObject への参照は、各関数に引数として渡すこともできます。これにより、所有権の問題も解決されます。

それ以外の場合、それがステートフルである場合、これは共有所有権の明らかなケースです。DoStuffWithRef は、LargeObject の単一のライブ インスタンスの有効期間をそれ自体の有効期間に実際に延長する必要があるためです。または、弱いポインターを使用して、実行時チェックのコストを消費します...

于 2015-01-19T06:55:59.860 に答える