クラスのコピーを防ぐために、プライベート コピー コンストラクター/代入演算子を非常に簡単に宣言できます。ただし、継承することもできますboost::noncopyable
。
この場合、ブーストを使用することの利点/欠点は何ですか?
クラスのコピーを防ぐために、プライベート コピー コンストラクター/代入演算子を非常に簡単に宣言できます。ただし、継承することもできますboost::noncopyable
。
この場合、ブーストを使用することの利点/欠点は何ですか?
他の人が言ったことを要約すると:
boost::noncopyable
プライベート コピー方法に対する利点:
noncopyable
.プライベート コピー方式の利点boost::noncopyable
:
それは意図を明示的かつ明確にします。それ以外の場合は、クラスの定義を確認し、コピーセマンティックに関連する宣言を検索し、それが宣言されているアクセス指定子を探して、クラスがコピー不可かどうか。コピーセマンティックを有効にしてコンパイルエラーを確認する必要があるコードを書くことによってそれを発見する別の方法。
なぜ誰もそれについて言及していないように見えるのか理解できませんが、:
あなたと一緒noncopyable
にあなたのクラスの名前を一度だけ書いてください。
なしの場合、 5つの重複があります。1つは「クラスA」用、2つは割り当てを無効にするため、2つはコピーコンストラクターを無効にするためです。
ドキュメントの引用:
「これらに対処する従来の方法は、プライベート コピー コンストラクターとコピー割り当てを宣言し、それがなぜ行われたかを文書化することです。しかし、noncopyable からの派生は、より単純で明確であり、追加の文書を必要としません。」
http://www.boost.org/libs/utility/utility.htm#Class_noncopyable
具体的な利点の 1 つは (意図をもう少し明確に表現することを超えて)、メンバーまたはフレンド関数がオブジェクトをコピーしようとした場合に、リンク段階ではなくコンパイル段階で、エラーがより早く検出されることです。基本クラスのコンストラクター/代入はどこからでもアクセスできないため、コンパイル エラーが発生します。
また、誤って関数を定義すること (つまり、 の{}
代わりに入力すること;
) を防ぎます。小さなエラーは見過ごされがちですが、メンバーや友人がオブジェクトの無効なコピーを作成する可能性があります。
小さな欠点 (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++ にはいくつかの問題があることを知っています。とにかく、「問題」をチェックするコードは非常に単純化されています...時々それが役立ちます。
利点は、プライベート コピー コンストラクターとプライベート コピー オペレーターを自分で作成する必要がなく、追加のドキュメントを作成しなくても意図を明確に表現できることです。
コピー コンストラクターと代入演算子を手動で削除またはプライベート化するよりも、boost::noncopyable を使用したいと思います。
ただし、次の理由から、どちらの方法もほとんど使用しません。
コピーできないオブジェクトを作成している場合、コピーできない理由が必要です。この理由の 99% は、意味のあるコピーができないメンバーがいるからです。おそらく、そのようなメンバーは、プライベートな実装の詳細としても適しています。だから私はこのようなほとんどのクラスを次のようにします:
struct Whatever {
Whatever();
~Whatever();
private:
struct Detail;
std::unique_ptr<Detail> detail;
};
これで、プライベート実装構造体ができました。std::unique_ptr を使用したため、トップレベル クラスは無料でコピーできません。これに起因するリンク エラーは、std::unique_ptr をコピーできないことについて話しているため、理解できます。私にとっては、これが boost::noncopyable のすべての利点であり、プライベートな実装が 1 つにまとめられたものです。
このパターンの利点は後で、このクラスのオブジェクトを本当にコピー可能にしたいと判断した場合、クラス階層を変更せずに、コピー コンストラクターや代入演算子を追加して実装するだけで済みます。