名稱空間
變體
操作

賦值運算子

來自 cppreference.com
< cpp‎ | 語言
 
 
C++ 語言
 
 

賦值運算子修改物件的值。

運算子名稱  語法  可過載 原型示例(對於 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);
注意
  • 所有內建賦值運算子都返回 *this,大多數使用者定義過載也返回 *this,以便使用者定義的運算子可以像內建運算子一樣使用。然而,在使用者定義運算子過載中,任何型別都可以用作返回型別(包括 void)。
  • T2 可以是包括 T 在內的任何型別。

目錄

[編輯] 定義

複製賦值將物件 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 開始)
  1. target-expr 必須具有比賦值表示式更高的優先順序
  2. new-value 不能是逗號表示式,因為它的優先順序較低。
1) 簡單賦值表示式。
2) 複合賦值表示式。

如果 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-exprnew-value 標識重疊物件,則行為未定義(除非重疊完全且型別相同)。

如果 target-expr 的型別是 volatile 限定的,則賦值被棄用,除非(可能帶括號的)賦值表示式是丟棄值表示式未求值運算元

(C++20 起)


從非表示式初始化子句賦值

new-value 僅在以下情況才允許不是表示式:

  • target-expr標量型別 T,並且 new-value 為空或只有一個元素。在這種情況下,給定一個發明的變數 t 宣告並初始化為 T t = new-value x = new-value  的含義是 x = t
  • target-expr 是類型別。在這種情況下,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);

對於每對 A1A2,其中 A1 是算術型別(可選 volatile 限定),A2 是提升的算術型別,以下函式簽名參與過載決議:

A1& operator=(A1&, A2);

[編輯] 內建複合賦值運算子

每個內建複合賦值表示式 target-expr op = new-value 的行為與表示式 target-expr = target-expr op new-value 的行為完全相同,除了 target-expr 只被求值一次。

對內建簡單賦值運算子的 target-exprnew-value 的要求也適用。此外

  • 對於 +=-=target-expr 的型別必須是算術型別或指向(可能 cv 限定的)完全定義物件型別的指標。
  • 對於所有其他複合賦值運算子,target-expr 的型別必須是算術型別。

針對使用者定義運算子的過載決議中,對於每對 A1A2,其中 A1 是算術型別(可選 volatile 限定),A2 是提升的算術型別,以下函式簽名參與過載決議:

A1& operator*=(A1&, A2);
A1& operator/=(A1&, A2);
A1& operator+=(A1&, A2);
A1& operator-=(A1&, A2);

對於每對 I1I2,其中 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)
TE1 的型別),這引入了 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 += b
a -= b
a *= b
a /= b
a %= b
a &= b
a |= b
a ^= b
a <<= b
a >>= b

++a
--a
a++
a--

+a
-a
a + b
a - b
a * b
a / b
a % b
~a
a & b
a | b
a ^ b
a << b
a >> b

!a
a && b
a || b

a == b
a != b
a < b
a > b
a <= b
a >= b
a <=> b

a[...]
*a
&a
a->b
a.b
a->*b
a.*b

函式呼叫

a(...)
逗號

a, b
條件

a ? b : c
特殊運算子

static_cast 將一種型別轉換為另一種相關型別
dynamic_cast 在繼承層次結構內進行轉換
const_cast 新增或移除 cv-限定符
reinterpret_cast 將型別轉換為不相關型別
C 風格轉換透過 static_castconst_castreinterpret_cast 的混合將一種型別轉換為另一種型別
new 建立具有動態儲存期的物件
delete 銷燬先前由 new 表示式建立的物件並釋放獲得的記憶體區域
sizeof 查詢型別的大小
sizeof... 查詢 的大小 (C++11 起)
typeid 查詢型別的型別資訊
noexcept 檢查表示式是否可以丟擲異常 (C++11 起)
alignof 查詢型別的對齊要求 (C++11 起)

C 文件,關於 賦值運算子