代入演算子¶
演算子オーバーロードの対象して代入演算子もあります。
代入演算子にはコピー代入演算子とムーブ代入演算子の2つがあります。
コピー代入演算子¶
コピー代入演算子は通常以下を満たすメンバ関数として定義します。
- 引数はコピー元となるオブジェクトの
const
左辺値参照 - 戻り値はコピー先オブジェクト (自オブジェクト) の左辺値参照
class Copyable {
public:
Copyable(); // デフォルトコンストラクタ
Copyable& operator=(const Copyable& c); // コピー代入演算子
};
コピー代入演算子を使用するには次のようにします。
Copyable c1; // デフォルトコンストラクタでオブジェクト作成
Copyable c2; // デフォルトコンストラクタでオブジェクト作成
c2 = c1; // コピー代入演算子でコピー代入
一般にコピーコンストラクタとコピー代入演算子はセットで使用します。
class Copyable {
public:
Copyable(); // デフォルトコンストラクタ
Copyable(const Copyable& c); // コピーコンストラクタ
Copyable& operator=(const Copyable& c); // コピー代入演算子
};
コピー代入演算子を定義していないクラスでは コンパイラによって暗黙的にコピー代入演算子が定義されます。
暗黙的にコピー代入演算子が定義されないケース
コピー代入演算子を定義していないクラスであっても、 特定の条件を満たした場合には暗黙的なコピー代入演算子の定義は行われなくなります。
条件の一例として次のものがあります。
- コピー代入演算子が定義されていないデータメンバをもつ
- 下記のいずれかが明示的に定義されている
- ムーブコンストラクタ
- ムーブ代入演算子
詳細は コピー代入演算子 - cppreference.com を参照してください。
ムーブ代入演算子¶
ムーブ代入演算子は通常以下を満たすメンバ関数として定義します。
- 引数はムーブ元となるオブジェクトの右辺値参照
- 戻り値はムーブ先オブジェクト (自オブジェクト) の左辺値参照
class Movable {
public:
Movable(); // デフォルトコンストラクタ
Movable& operator=(Movable&& m); // ムーブ代入演算子
};
ムーブ代入演算子を使用するには次のようにします。
Movable m1; // デフォルトコンストラクタでオブジェクト作成
Movable m2; // デフォルトコンストラクタでオブジェクト作成
m2 = std::move(m1); // ムーブ代入演算子でムーブ代入
一般にムーブコンストラクタとムーブ代入演算子はセットで使用します。
class Movable {
public:
Movable(); // デフォルトコンストラクタ
Movable(Movable&& m); // ムーブコンストラクタ
Movable& operator=(Movable&& m); // ムーブ代入演算子
};
ムーブ代入演算子を定義していないクラスでは コンパイラによって暗黙的にムーブ代入演算子が定義されます。
暗黙的にムーブ代入演算子が定義されないケース
ムーブ代入演算子を定義していないクラスであっても、 特定の条件を満たした場合には暗黙的なムーブ代入演算子の定義は行われなくなります。
条件の一例として次のものがあります。
- ムーブ代入演算子が定義されていないデータメンバをもつ
- 下記のいずれかが明示的に定義されている
- コピーコンストラクタ
- コピー代入演算子
- ムーブコンストラクタ
- デストラクタ
詳細は ムーブ代入演算子 - cppreference.com を参照してください。
初期化¶
C++ では代入と初期化が区別されます。
変数宣言と同時に使用する =
は代入ではなく初期化として扱われます。
コピー初期化¶
初期化をコピーによって行う場合、 コピー代入演算子ではなくコピーコンストラクタが使用されます。
Copyable c1;
Copyable c2 = c1; // コピーコンストラクタを使用
Copyable c3;
c3 = c2; // コピー代入演算子を使用
ムーブ初期化¶
初期化をムーブによって行う場合、 ムーブ代入演算子ではなくムーブコンストラクタが使用されます。
Movable m1;
Movable m2 = std::move(m1); // ムーブコンストラクタを使用
Movable m3;
m3 = std::move(m2); // ムーブ代入演算子を使用