あるclassのメンバ変数にclassオブジェクトを持つ場合の一版的な実装方法

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
hogefoo

あるclassのメンバ変数にclassオブジェクトを持つ場合の一版的な実装方法

#1

投稿記事 by hogefoo » 5年前

タイトルの通り、class のメンバ変数がクラスオブジェクトの場合、どのようなパターンが一般的な実装方法なのか分かりません。
具体的には、次のような問題が起きています。

コード:

class Hoge
{
 public:
  Hoge(const Hoge&) = delete;
  Hoge& operator=(const Hoge&) = delete;  
 private:
  std::vector<int> a; // 大きい
  
}

class Foo
{
 public:
  Hoge get_hoge() const {return hoge;}
 private:
  Hoge hoge;
  Hoge2 hoge2; // このFooクラスは他のクラスオブジェクトもいろいろ持っている
}
このコードはコンパイルできません。Hogeはコピー禁止クラスなのに、Foo内のgetterでreturn時にコピーが発生するからです。
しかし、これの正しい修正方法が分かりません。

案1)Hogeをコピー可能にする
大きなオブジェクトを持っている場合、コピーは大きなコストになってしまいます。
案2)メンバ変数をpublicにする
一般的にはあまり良くないとされています。
実際、getter/seter には様々なメリットがあると解説されています。
案3)getterをconst参照で返す
これは、簡単に破壊的なコードがかけるため御法度だそうです。

となると、どのように書くべきなのかがわからなくなってしまいました。
どなたかご教授願います。

また、もう1つ質問があるのですが、
Fooのようなクラスのメンバ変数は、
Hoge* hoge;
のようにポインタで持つべきでしょうか。

アバター
h2so5
副管理人
記事: 2212
登録日時: 9年前
住所: 東京
連絡を取る:

Re: あるclassのメンバ変数にclassオブジェクトを持つ場合の一版的な実装方法

#2

投稿記事 by h2so5 » 5年前

今回のようなコピーコストが問題になる場合はhogeをshared_ptr<Hoge>で持ってgetterもそのスマートポインタを返すのが良いと思います。

アバター
tk-xleader
記事: 153
登録日時: 9年前
連絡を取る:

Re: あるclassのメンバ変数にclassオブジェクトを持つ場合の一版的な実装方法

#3

投稿記事 by tk-xleader » 5年前

案3ってそんなに問題でしょうか?
確かにキャストをすればmutableな参照を作り出すことはできますが、const外しの明示的なキャスト自体がそもそも不自然なコードですからconst参照を返すのがご法度というのは言いすぎなような気がします。

constexpr
記事: 5
登録日時: 5年前

Re: あるclassのメンバ変数にclassオブジェクトを持つ場合の一版的な実装方法

#4

投稿記事 by constexpr » 5年前

案3が御法度な理由がわからないが。const参照で返すなら変更はできないはず。ただの参照やアドレスを返す場合と混同しているのではないか。

そもそもコピーで返す場合とポインタを所持してポインタを渡す場合では、実行結果が変わる。もし問題にならないのであればそれは読み取り操作のみなのだから、const参照が適切だろう。
もし変更を行いたいのであれば、そもそもコピーではメンバ変数を変更できない。h2so5さんの言うように共有可能なスマートポインタを使うなど、他の実装をする必要がある。

閉鎖

“C言語何でも質問掲示板” へ戻る