賦值運算子
賦值運算子修改物件的值。
運算子名稱 | 語法 | 可過載 | 原型示例(對於 class T) | |
---|---|---|---|---|
類定義內部 | 類定義外部 | |||
簡單賦值 | a = b
|
是 | T& T::operator =(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); |
取餘賦值 | 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); |
按位右移賦值 | 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 的結果是對應的有符號/無符號整型,則物件的值將替換為型別 T
的值,其值表示與 new-value 的結果相同。
內建簡單賦值的結果是 target-expr 型別的左值,引用 target-expr。如果 target-expr 是位域,則結果也是位域。
[編輯] 從表示式賦值
如果 new-value 是表示式,它會隱式轉換為 target-expr 的 cv-無限定型別。當 target-expr 是不能表示表示式值的位域時,位域的最終值是實現定義的。
如果 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 的要求也適用。此外
在針對使用者定義運算子的過載決議中,對於每對 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++ 標準。
缺陷報告 | 應用於 | 釋出時的行為 | 正確的行為 |
---|---|---|---|
CWG 1527 | C++11 | 對於類型別物件的賦值,右運算元 只能是初始化列表,當賦值 由使用者定義的賦值運算子定義時 |
移除使用者定義 賦值約束 |
CWG 1538 | C++11 | E1 = {E2} 等價於 E1 = T(E2) ( T 是 E1 的型別),這引入了 C 風格的轉換 |
它等價於 E1 = T{E2} |
CWG 2654 | C++20 | volatile 限定型別的複合賦值運算子 被不一致地棄用 |
它們都沒有 被棄用 |
CWG 2768 | C++11 | 從非表示式初始化子句賦值 到標量值會執行直接列表初始化 |
改為執行復制列表 初始化 |
CWG 2901 | C++98 | 透過 int 左值賦值給 unsigned int 物件的值不明確 |
已明確 |
P2327R1 | C++20 | volatile 型別的按位複合賦值運算子 在某些平臺上很有用,但被棄用 |
它們沒有 被棄用 |
[編輯] 另請參閱
常見運算子 | ||||||
---|---|---|---|---|---|---|
賦值 | 遞增 遞減 |
算術 | 邏輯 | 比較 | 成員 訪問 |
其他 |
a = b |
++a |
+a |
!a |
a == b |
a[...] |
函式呼叫 a(...) |
逗號 a, b | ||||||
條件 a ? b : c | ||||||
特殊運算子 | ||||||
static_cast 將一種型別轉換為另一種相關型別 |
C 文件,關於 賦值運算子
|