77

クラスのコピーを防ぐために、プライベート コピー コンストラクター/代入演算子を非常に簡単に宣言できます。ただし、継承することもできますboost::noncopyable

この場合、ブーストを使用することの利点/欠点は何ですか?

4

11 に答える 11

46

他の人が言ったことを要約すると:

boost::noncopyableプライベート コピー方法に対する利点:

  1. 意図においてより明示的で説明的です。プライベート コピー機能の使用は、noncopyable.
  2. コードが少なくなり、入力が少なくなり、混乱が少なくなり、エラーの余地が少なくなります (最も簡単なのは、誤って実装を提供することです)。
  3. C# 属性と同様に、型のメタデータに意味を埋め込みます。コピー不可能なオブジェクトのみを受け入れる関数を記述できるようになりました。
  4. ビルド プロセスの早い段階でエラーをキャッチする可能性があります。クラス自体またはクラスの友人が誤ったコピーを行っている場合、エラーはリンク時ではなくコンパイル時に表示されます。
  5. (#4 とほぼ同じ) クラス自体またはクラスのフレンドがプライベート コピー メソッドを呼び出せないようにします。

プライベート コピー方式の利点boost::noncopyable:

  1. ブースト依存なし
于 2011-10-20T16:29:18.413 に答える
44

それは意図を明示的かつ明確にします。それ以外の場合は、クラスの定義を確認し、コピーセマンティックに関連する宣言を検索し、それが宣言されているアクセス指定子を探して、クラスがコピー不可かどうか。コピーセマンティックを有効にしてコンパイルエラーを確認する必要があるコードを書くことによってそれを発見する別の方法。

于 2011-10-19T15:43:21.010 に答える
17
  1. boost::noncopyable の意図はより明確です。
  2. Boost::noncopyable は、クラス メソッドがプライベート コピー コンストラクターを誤って使用するのを防ぎます。
  3. boost::noncopyable による少ないコード。
于 2011-10-19T15:44:52.483 に答える
16

なぜ誰もそれについて言及していないように見えるのか理解できませんが、:

あなたと一緒noncopyableにあなたのクラスの名前を一度だけ書いてください。

なしの場合、 5つの重複があります。1つは「クラスA」用、2つは割り当てを無効にするため、2つはコピーコンストラクターを無効にするためです。

于 2011-10-30T09:29:58.830 に答える
10

ドキュメントの引用:

「これらに対処する従来の方法は、プライベート コピー コンストラクターとコピー割り当てを宣言し、それがなぜ行われたかを文書化することです。しかし、noncopyable からの派生は、より単純で明確であり、追加の文書を必要としません。」

http://www.boost.org/libs/utility/utility.htm#Class_noncopyable

于 2011-10-19T15:45:10.893 に答える
8

具体的な利点の 1 つは (意図をもう少し明確に表現することを超えて)、メンバーまたはフレンド関数がオブジェクトをコピーしようとした場合に、リンク段階ではなくコンパイル段階で、エラーがより早く検出されることです。基本クラスのコンストラクター/代入はどこからでもアクセスできないため、コンパイル エラーが発生します。

また、誤って関数を定義すること (つまり、 の{}代わりに入力すること;) を防ぎます。小さなエラーは見過ごされがちですが、メンバーや友人がオブジェクトの無効なコピーを作成する可能性があります。

于 2011-10-19T15:45:21.250 に答える
4

小さな欠点 (GCC 固有) は、プログラムをコンパイルし、ポインターを含むクラスがある場合です。g++ -Weffc++

class C : boost::noncopyable
{
public:
  C() : p(nullptr) {}

private:
  int *p;
};

GCCは何が起こっているのか理解していません:

警告: 'class C' にはポインター データ メンバーがあります [-Weffc++]
警告: ただし、'C(const S&)' をオーバーライドしません [-Weffc++]
警告: または 'operator=(const C&)' [-Weffc++]

それは文句を言いませんが:

#define DISALLOW_COPY_AND_ASSIGN(Class) \
  Class(const Class &) = delete;     \
  Class &operator=(const Class &) = delete

class C
{
public:
  C() : p(nullptr) {}
  DISALLOW_COPY_AND_ASSIGN(C);

private:
  int *p;
};

PS GCC の -Weffc++ にはいくつかの問題があることを知っています。とにかく、「問題」をチェックするコードは非常に単純化されています...時々それが役立ちます。

于 2014-03-05T12:09:22.983 に答える
3

利点は、プライベート コピー コンストラクターとプライベート コピー オペレーターを自分で作成する必要がなく、追加のドキュメントを作成しなくても意図を明確に表現できることです。

于 2011-10-19T15:43:38.480 に答える
2

コピー コンストラクターと代入演算子を手動で削除またはプライベート化するよりも、boost::noncopyable を使用したいと思います。

ただし、次の理由から、どちらの方法もほとんど使用しません。

コピーできないオブジェクトを作成している場合、コピーできない理由が必要です。この理由の 99% は、意味のあるコピーができないメンバーがいるからです。おそらく、そのようなメンバーは、プライベートな実装の詳細としても適しています。だから私はこのようなほとんどのクラスを次のようにします:

struct Whatever {
  Whatever();
  ~Whatever();
  private:
  struct Detail;
  std::unique_ptr<Detail> detail;
};

これで、プライベート実装構造体ができました。std::unique_ptr を使用したため、トップレベル クラスは無料でコピーできません。これに起因するリンク エラーは、std::unique_ptr をコピーできないことについて話しているため、理解できます。私にとっては、これが boost::noncopyable のすべての利点であり、プライベートな実装が 1 つにまとめられたものです。

このパターンの利点は後で、このクラスのオブジェクトを本当にコピー可能にしたいと判断した場合、クラス階層を変更せずに、コピー コンストラクターや代入演算子を追加して実装するだけで済みます。

于 2011-10-20T19:03:22.517 に答える