web-dev-qa-db-ja.com

このC ++オブジェクトをコピー不可にするにはどうすればよいですか?

タイトルを参照してください。

私が持っています:

class Foo {
   private:
     Foo();
   public:
     static Foo* create();
}

Fooをコピー不可にするには、ここから何をする必要がありますか?

ありがとう!

64
anon
class Foo {
   private:
     Foo();
     Foo( const Foo& ); // non construction-copyable
     Foo& operator=( const Foo& ); // non copyable
   public:
     static Foo* create();
}

ブーストを使用している場合、コピー不可から継承することもできます: http://www.boost.org/doc/libs/1_41_0/boost/noncopyable.hpp

編集:この機能をサポートするコンパイラがある場合、C++ 11バージョン:

class Foo {
   private:
     Foo();
     Foo( const Foo& ) = delete; // non construction-copyable
     Foo& operator=( const Foo& ) = delete; // non copyable
   public:
     static Foo* create();
}
88
Klaim

コピーコンストラクタと代入演算子もプライベートにします。宣言だけで十分です。実装を提供する必要はありません。

25
Hans Passant
#include <boost/utility.hpp>
class Foo : boost::noncopyable {...

しかし、スコット・マイヤーズがかつて言ったように...「それは素晴らしいクラスです、それはちょうど私が少し不名誉であると思うことです」、またはそのような何か。

17
Chris H

コピーコンストラクタを禁止するもう1つの方法、便宜上、DISALLOW_COPY_AND_ASSIGNマクロを使用できます。

// A macro to disallow the copy constructor and operator= functions
// This should be used in the private: declarations for a class
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
  TypeName(const TypeName&) = delete;      \
  void operator=(const TypeName&) = delete

次に、クラスFooで:

class Foo {
 public:
  Foo(int f);
  ~Foo();

 private:
  DISALLOW_COPY_AND_ASSIGN(Foo);
};

Googleスタイルシートからの参照

17
yesraaj

そこに少し追加します。

従来の解決策は、前述したように、Copy ConstructorAssignment Operatorの両方をprivateとしてdeclareに、notdefineそれら。

  • これらはprivateであるため、クラスのプライベート部分にアクセスできないユーザーを使用しようとすると、コンパイル時エラーが発生します。 ..
  • link-timeのいずれかのundefined symbolの形式でエラーが発生する友人(およびクラス自体)を残すそこにあるものをチェックします)、またはおそらくrun-time(ライブラリをロードしようとしたとき)。

もちろん、エラーが発生したファイルと行の指示がないため、コードを自分で確認する必要があるため、2番目のケースではかなり面倒です。幸いなことに、それはクラスのメソッドと友人​​に限定されています。


また、これらのプロパティは継承と合成の道を推移することに注意する価値があります。コンパイラはDefault ConstructorCopy ConstructorAssignment Operator、およびDestructorのデフォルトバージョンのみを生成しますかもしれない。

これは、これらの4つのいずれについても、クラスのすべてのベースと属性にアクセスできる場合、自動的に生成されるonlyことを意味します。

// What does boost::noncopyable looks like >
class Uncopyable {
public:
  Uncopyable() {}

private:
  Uncopyable(const Uncopyable&);
  Uncopyable& operator=(const Uncopyable&);
};

このため、このクラスから継承する(または属性として使用する)ことにより、自分でこれらの演算子を定義しない限り、クラスのコピーや割り当てが事実上できなくなります。

一般に、2つの理由から、構成よりも継承が選択されます。

  • ポリモーフィズムがそれほど有用でない場合でも、オブジェクトは事実上Uncopyableです
  • 継承はEBOまたはEmpty Base Optimizationにつながりますが、属性はアドレス可能であるため、実際には必要ではなくても(クラスの各インスタンスで)メモリを占有しますが、コンパイラはこのオーバーヘッドを追加しない可能性があります基本クラス。

または、演算子をプライベートとして宣言し、独自のクラスで定義しないこともできますが、コードはself-documentingより少なくなります。このプロパティを持つクラスを自動的に検索できるようになります(本格的なパーサーがない限り)。

これがメカニズムにいくらかの光を当てることを願っています。

16
Matthieu M.

C++ 11では、宣言の後に= deleteを配置することにより、デフォルトのコピーおよび割り当てコンストラクターの作成を明示的に無効にできます。

From Wikipedia

struct NonCopyable {
    NonCopyable() = default;
    NonCopyable(const NonCopyable&) = delete;
    NonCopyable & operator=(const NonCopyable&) = delete;
};

もちろん、クラスにも同じことが言えます。

11
bobbaluba

C++オブジェクトをコピー不可にする一般的な方法は、コピーコンストラクターとコピー割り当て演算子を明示的に宣言し、それらを実装しないことです。これにより、コンパイラが独自に生成するのを防ぎます。 (通常、これはprivateの宣言と組み合わせて行われるため、リンカエラーではなくコンパイルエラーが生成されます。)

boost::noncopyable 継承可能なクラス。上記で説明したことを行います。

4
jamesdlin

コピーコンストラクタをプライベートにします。

Foo(const Foo& src);

実装する必要はなく、ヘッダーファイルで宣言するだけです。

3
Roland Rabien

これは私が使用するものです:

/* Utility classes */

struct NoCopy
{
public:
    NoCopy() {}
private:
    NoCopy(const NoCopy &);
};

struct NoAssign
{
private:
    NoAssign &operator=(const NoAssign &);
};

struct NonInstantiable
{
private:
    NonInstantiable();
};

struct NoCopyAssign : NoCopy, NoAssign
{
};
typedef NoCopyAssign NoAssignCopy;

あなたの場合:

struct Example : NoCopy
{
};
2
Thomas Bonini

C++ 11の良い習慣は、コピーコンストラクターと割り当てをパブリックに削除されたものとして宣言することです。非公開ではなく、publicly削除: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rc-delete

1