Scott Meyers による効果的な C++ を読んだ後、次の解決策があります。
遅延評価 (参照カウント付き) を行うテンプレートを定義します。
class Obj : private lazy<Obj_data>{};
怠惰な人は Obj_data を非公開で保存し、アクセサーを保護し、1 つは変更用、もう 1 つは読み取り専用アクセス用です。
修飾子アクセサーは、必要に応じて最初に をディープ コピーしObj_data
、次にデータへの参照を渡します。読み取り専用アクセサーは const 参照を返すだけです。
これの全体的なコストは、2 つの余分なポインター (データ用に 1 つとカウンター用に 1 つ) とカウンターを格納することです。
実装は次のようなものです。
class lazy{
protected:
lazy(const lazy&obj){lazy_copy(obj);}
//(the required constructors, operator= ...)
// accessors:
const Obj_data& data() const {return *od;}
Obj_data& mod_data() {make_private(); return *od;}
private:
void lazy_copy(const lazy& obj);
void make_private(); // this does the actual deep-copy, as late as possible.
private:
counter*;
Obj_data* od;
};
したがって、 go の属性の読み取りとObj
変更
void Obj::method(){
cout << data().some_attribute; // simple read
mod_data().i = 10; // simple modify
const Obj_data& const_d = data(); // assignable for lots of read-outs
Obj_data& var_d = mod_data(); // assignable for lots of modifications.
}
クラスの非 const 関数としてのみメンバーdata()
で使用できることに注意してください。したがって、このソリューションはオーバーヘッドがほとんどなく、完全に安全です。const
mod_data()
理論的背景: 質問の望ましい動作は実装の詳細であり、クライアントには関係ありません。したがって、プライベート継承で解決します。