代入演算子
代入演算子はオブジェクトの値を変更します。
| 演算子名 | 構文 | オーバーロード可能 | プロトタイプの例 (class T の場合) | |
|---|---|---|---|---|
| クラス定義内 | クラス定義外 | |||
| 単純代入 | a = b
|
はい | T& T::operator =(const T2& b); | N/A |
| 加算代入 | a += b
|
はい | T& T::operator +=(const T2& b); | T& operator +=(T& a, const T2& b); |
| 減算代入 | a -= b
|
はい | T& T::operator -=(const T2& b); | T& operator -=(T& a, const T2& b); |
| 乗算代入 | a *= b
|
はい | T& T::operator *=(const T2& b); | T& operator *=(T& a, const T2& b); |
| 除算代入 | a /= b
|
はい | T& T::operator /=(const T2& b); | T& operator /=(T& a, const T2& b); |
| 剰余代入 | a %= b
|
はい | T& T::operator %=(const T2& b); | T& operator %=(T& a, const T2& b); |
| ビットAND代入 | a &= b
|
はい | T& T::operator &=(const T2& b); | T& operator &=(T& a, const T2& b); |
| ビットOR代入 | a |= b
|
はい | T& T::operator |=(const T2& b); | T& operator |=(T& a, const T2& b); |
| ビットXOR代入 | a ^= b
|
はい | T& T::operator ^=(const T2& b); | T& operator ^=(T& a, const T2& b); |
| ビット左シフト代入 | a <<= b
|
はい | T& T::operator <<=(const T2& b); | T& operator <<=(T& a, const T2& b); |
| ビット右シフト代入 | a >>= b
|
はい | T& T::operator >>=(const T2& b); | T& operator >>=(T& a, const T2& b); |
| ||||
目次 |
[編集] 定義
コピー代入は、オブジェクト a の内容を b の内容のコピーで置き換えます(b は変更されません)。クラス型の場合、これは特殊メンバ関数によって実行され、「コピー代入演算子」で説明されています。
|
ムーブ代入は、オブジェクト a の内容を b の内容で置き換えます。可能であればコピーを回避します(b は変更される場合があります)。クラス型の場合、これは特殊メンバ関数によって実行され、「ムーブ代入演算子」で説明されています。 |
(C++11以降) |
非クラス型の場合、コピー代入とムーブ代入は区別がつかず、直接代入と呼ばれます。
複合代入は、オブジェクト a の内容を、a の以前の値と b の値との二項演算の結果で置き換えます。
[編集] 代入演算子の構文
代入式は次の形式をとります。
target-expr = new-value |
(1) | ||||||||
| target-expr op new-value | (2) | ||||||||
| target-expr | - | 代入される式[1] |
| op | - | *=、/= %=、+= -=、<<=、>>=、&=、^=、|= のいずれか |
| new-value | - | ターゲットに代入される 式[2](C++11まで)初期化子句(C++11以降) |
|
new-value が式でない場合、代入式はオーバーロードされた複合代入演算子に一致することはありません。 |
(C++11以降) |
[編集] 組み込み単純代入演算子
組み込み単純代入の場合、target-expr は変更可能な左辺値である必要があります。
target-expr が参照するオブジェクトは、new-value の結果でその値を置き換えることによって変更されます。参照されているオブジェクトが整数型 T で、new-value の結果が対応する符号付き/符号なし整数型である場合、オブジェクトの値は、new-value の結果と同じ値表現を持つ型 T の値で置き換えられます。
組み込み単純代入の結果は、target-expr を参照する target-expr 型の左辺値です。target-expr が ビットフィールドの場合、結果もビットフィールドになります。
[編集] 式からの代入
new-value が式である場合、それは target-expr の cv-修飾されていない型に 暗黙的に変換されます。target-expr が式の値を表現できないビットフィールドである場合、ビットフィールドのresulting値は実装定義です。
target-expr と new-value が重複するオブジェクトを識別する場合、動作は未定義です(重複が完全で型が同じである場合を除く)。
|
target-expr の型が volatile 修飾されている場合、代入は非推奨です。ただし、(必要に応じて括弧で囲まれた)代入式が 破棄値式 または 評価対象外オペランドである場合を除きます。 |
(C++20以降) |
初期化子句(式でない)からの代入new-value が式でないことが許可されるのは、次の状況のみです。
#include <complex> std::complex<double> z; z = {1, 2}; // meaning z.operator=({1, 2}) z += {1, 2}; // meaning z.operator+=({1, 2}) int a, b; a = b = {1}; // meaning a = b = 1; a = {1} = b; // syntax error |
(C++11以降) |
ユーザー定義演算子に対するオーバーロード解決では、すべての型 T について、次の関数シグネチャがオーバーロード解決に参加します。
| T*& operator=(T*&, T*); |
||
| T*volatile & operator=(T*volatile &, T*); |
||
すべての列挙型またはメンバーへのポインタ型 T(オプションで volatile 修飾可能)について、次の関数シグネチャがオーバーロード解決に参加します。
| T& operator=(T&, T); |
||
すべてのペア A1 と A2 について、ここで A1 は算術型(オプションで volatile 修飾可能)であり、A2 は昇格された算術型である場合、次の関数シグネチャがオーバーロード解決に参加します。
| A1& operator=(A1&, A2); |
||
[編集] 組み込み複合代入演算子
すべての組み込み複合代入式 target-expr op = new-value の動作は、式 target-expr = target-expr op new-value の動作とまったく同じですが、target-expr は一度だけ評価されます。
組み込み単純代入演算子の target-expr および new-value に対する要件も適用されます。さらに、
- += および -= の場合、target-expr の型は 算術型、または(オプションで cv 修飾された)完全に定義された オブジェクト型 へのポインタである必要があります。
- 他のすべての複合代入演算子の場合、target-expr の型は算術型である必要があります。
ユーザー定義演算子に対するオーバーロード解決では、すべてのペア A1 と A2 について、ここで A1 は算術型(オプションで volatile 修飾可能)であり、A2 は昇格された算術型である場合、次の関数シグネチャがオーバーロード解決に参加します。
| A1& operator*=(A1&, A2); |
||
| A1& operator/=(A1&, A2); |
||
| A1& operator+=(A1&, A2); |
||
| A1& operator-=(A1&, A2); |
||
すべてのペア I1 と I2 について、ここで I1 は整数型(オプションで volatile 修飾可能)であり、I2 は昇格された整数型である場合、次の関数シグネチャがオーバーロード解決に参加します。
| I1& operator%=(I1&, I2); |
||
| I1& operator<<=(I1&, I2); |
||
| I1& operator>>=(I1&, I2); |
||
| I1& operator&=(I1&, I2); |
||
| I1& operator^=(I1&, I2); |
||
| I1& operator|=(I1&, I2); |
||
すべての(オプションで cv 修飾された)オブジェクト型 T について、次の関数シグネチャがオーバーロード解決に参加します。
| T*& operator+=(T*&, std::ptrdiff_t); |
||
| T*& operator-=(T*&, std::ptrdiff_t); |
||
| T*volatile & operator+=(T*volatile &, std::ptrdiff_t); |
||
| T*volatile & operator-=(T*volatile &, std::ptrdiff_t); |
||
[編集] 例
#include <iostream> int main() { int n = 0; // not an assignment n = 1; // direct assignment std::cout << n << ' '; n = {}; // zero-initialization, then assignment std::cout << n << ' '; n = 'a'; // integral promotion, then assignment std::cout << n << ' '; n = {'b'}; // explicit cast, then assignment std::cout << n << ' '; n = 1.0; // floating-point conversion, then assignment std::cout << n << ' '; // n = {1.0}; // compiler error (narrowing conversion) int& r = n; // not an assignment r = 2; // assignment through reference std::cout << n << ' '; int* p; p = &n; // direct assignment p = nullptr; // null-pointer conversion, then assignment std::cout << p << ' '; struct { int a; std::string s; } obj; obj = {1, "abc"}; // assignment from a braced-init-list std::cout << obj.a << ':' << obj.s << '\n'; }
実行結果の例
1 0 97 98 1 2 (nil) 1:abc
[編集] 不具合報告
以下の動作変更を伴う欠陥報告が、以前に公開されたC++標準に遡って適用されました。
| DR | 適用対象 | 公開された動作 | 正しい動作 |
|---|---|---|---|
| CWG 1527 | C++11 | クラス型オブジェクトへの代入において、右オペランドは 初期化子リストになりうるのは、代入が ユーザー定義代入演算子によって定義されている場合のみ |
ユーザー定義の 代入制約を削除 |
| CWG 1538 | C++11 | E1 = {E2} は E1 = T(E2) に等価でした ( T は E1 の型)、これは C スタイルのキャストを導入しました。 |
等価になりました ~ E1 = T{E2} |
| CWG 2654 | C++20 | volatile 修飾された型の複合代入演算子は、一貫性がなく非推奨でした。 それらの none |
は非推奨です。 非推奨です。 |
| CWG 2768 | C++11 | 式でない初期化子句からの スカラー値への代入は、直接リスト初期化を実行していました。 |
コピーリスト 初期化を実行します。 |
| CWG 2901 | C++98 | int 左辺値を通じた unsigned int オブジェクトへの代入は不明瞭です。 |
明確化された |
| P2327R1 | C++20 | volatile 型のビット単位複合代入演算子 一部のプラットフォームで有用でありながら非推奨になりました。 |
ならない deprecated |
[編集] 関連項目
| 共通の演算子 | ||||||
|---|---|---|---|---|---|---|
| 代入 | インクリメント デクリメント |
算術 | 論理 | 比較 | メンバ アクセス |
その他 |
|
a = b |
++a |
+a |
!a |
a == b |
a[...] |
関数呼び出し a(...) |
| コンマ a, b | ||||||
| conditional a ? b : c | ||||||
| 特殊な演算子 | ||||||
|
static_castは、ある型を関連する別の型に変換する | ||||||
| C ドキュメント (代入演算子)
|