web-dev-qa-db-ja.com

初期化できるが割り当てられていないオブジェクト

オブジェクトを初期化できるが割り当てられないクラスを作成する必要があります。

代入演算子を定義しないことでこれを実行できるのではないかと思いましたが、コンパイラーはコンストラクターを使用して代入を行います。

このようにする必要があります:

Object a=1;    // OK
a=1;           // Error

どうすればできますか?

29
Galaxian

削除 代入演算子:

_#include <iostream>
using namespace std;

struct Object
{
    Object(int) {}
    Object& operator=(int) = delete;
};

int main()
{
    Object a=1;    // OK
    a=1;           // Error
}
_

代替ソリューション

explicit キーワードを使用できます。

_#include <iostream>
using namespace std;

struct Object
{
    explicit Object(int) {}
};

int main()
{
    Object a(1);    // OK - Uses explicit constructor
    a=1;           // Error
}
_

更新

コメントでuser2079303が述べたように:

代替ソリューションはa=Object(1)のような通常のコピー/移動割り当てを妨げないことに言及する価値があるかもしれません

これは以下を使用することで回避できます:Object& operator=(const Object&) = delete;

49
Jonas

aconstにすることでトリックが行われます

const Object a=1;    // OK

これで、aaとして宣言されているため、constに値を割り当てることができなくなります。 aconstとして宣言する場合、宣言時にaを初期化する必要があることに注意してください。

aconstとして宣言し、初期化すると、aに他の値を割り当てることができなくなります。

 a=1;   //error
58
Yousaf

これが代入演算子を定義しないことによってそうなることを望みました

コピー代入演算子(_const Object&_をパラメーターとして取る)が暗黙的に生成されるため、これは機能しません。また、_a = 1_を記述すると、生成されたコピー代入演算子が呼び出され、_1_が変換コンストラクターObject::Object(int)を介してObjectに暗黙的に変換されます。次に_a = 1;_は正常に動作します。

代入演算子は、intdeleted として明示的に宣言できます(C++ 11以降)。これは、多重定義解決でコピー割り当て演算子の前に選択されます。

関数がオーバーロードされている場合、オーバーロードの解決が最初に行われ、削除された関数が選択された場合にのみプログラムが不正な形式になります。

例えば.

_struct Object {
    Object(int) {}
    Object& operator=(int) = delete;
};
_

副作用のある他の解決策もあります。 Object::Object(int)explicitとして宣言して、intからObjectへの暗黙的な変換を禁止し、_a = 1_を失敗させることができます。ただし、コピーの初期化ではexplicitコンストラクタが考慮されないため、これにより_Object a = 1;_も失敗することに注意してください。または、コピー割り当て演算子を削除済みとしてマークすることもできますが、これによりObjects間の割り当ても失敗します。

13
songyuanyao

どうすればできますか?

オプション1:

コンストラクタを作るexplicit

struct Object
{
   explicit Object(int in) {}
};

オプション2:

delete代入演算子。

struct Object
{
   Object(int in) {}
   Object& operator=(int in) = delete;
};

上記の両方のオプションを使用できます。

struct Object
{
   explicit Object(int in) {}
   Object& operator=(int in) = delete;
};

オプション3:

初期化後に割り当てが必要ない場合は、deleteを引数の型として使用して、代入演算子をObjectできます。

struct Object
{
   explicit Object(int in) {}
   Object& operator=(Object const& in) = delete;
};

それは次の使用を防ぎます:

Object a(1);
a = Object(2); // Error
a = 2;         // Error
9
R Sahu

削除された関数はC++ 11以降でのみ使用できます。古いコンパイラの場合、代入演算子privateを作成できます。

struct Object
{
Object(int) {}
private: 
Object& operator=(int);
};

コンパイラはエラーをスローします

Object a=1; //ok
a=2; // error 

しかし、あなたはまだ行うことができます

Object a=1,b=2;
b=a;

デフォルトの代入演算子がコンパイラーによって生成されるのを妨げられないためです。したがって、デフォルトの割り当てprivateをマークすると、この問題が解決します。

struct Object
{
Object(int) {}
private: 
Object& operator=(Object&);
};
7
Mrnell