C 之 過載賦值操作符

2021-09-25 12:07:57 字數 2584 閱讀 5871

widget 中,有乙個 bitmap 型指標  pb

class

bitmap;

class

widget ;

在 widget 類中過載 "=" 時,需考慮以下方面

整數 15 首先賦值給 z,得到新值的 z 再賦值給 y,接著得到新值的 y 最後再賦值給 x,如下所示:

int

x, y, z;

x = y = z = 15; //

chain of assignments

相當於

x = (y = (z = 15));

為了實現鏈式賦值,函式的返回值須是乙個例項自身的引用,也即 *this;同理,過載其它的復合賦值運算子 (如 +=, -=, *=, /=),也必須在函式結束前返回 *this

widget& widget::operator=(const widget&rhs)

其次要考慮的是,關於自賦值的情況,雖然顯式的自賦值並不常見,但潛在的隱式自賦值仍需注意

widget  w;

...w = w; //

explict assignment to self

a[i] = a[j]; //

potential assignment to self

*px = *py; //

potential assignment to self

解決方法是,在函式內加乙個 if 語句,判斷當前例項 (*this) 和傳入的引數 rhs 是不是同乙個例項,也即判斷是不是自賦值的情況

如果是自賦值,則不作任何處理,直接返回 *this;如果不是自賦值,首先釋放例項自身已有記憶體,然後再分配新的記憶體,如下所示:

widget& widget::operator=(cosnt widget&rhs)

上例中,假如在分配記憶體時,因記憶體不足或 bitmap 的拷貝建構函式異常,導致 "new bitmap" 產生異常 (exception),則 pb 指向的是乙個已經被刪除的 bitmap

考慮異常安全,乙個方法是先用 new 分配新內容,再用 delete 釋放如下**的內容,如下所示:當 "new bitmap" 丟擲乙個異常時,pb 指標並不會改變

widget& widget::operator=(cosnt widget&rhs)

如果不考慮效率的問題,那麼即使沒有對自賦值進行判斷的 if 語句,其後面的語句也足以應付自賦值的問題

上例中,因為效率的問題,保留了 if 語句,但實際上,因為自賦值出現的概率很低,所以上述**看似「高效」,其實並不然

最常用的兼顧自賦值和異常安全 (exception safety) 的方法是 「拷貝-交換」 (copy-and-swap),如下所示:

widget& widget::operator=(const widget&rhs)

std::swap 屬於標準演算法,其實現如下:

namespace

std

}

以上有三個拷貝:首先拷貝 a 給 temp,然後拷貝 b 給 a,最後拷貝 temp 給 b

對於 widget 類,實現兩個 widget 物件的值交換,只需互換 bitmap *pb 即可,這稱為 pimpl (pointer to implementation)

首先,定義乙個 swap 公有成員函式,如下:

void widget::swap(widget&other)

然後,模板特例化 std::swap 函式,呼叫上面的 swap 函式,實現指標互換

namespace

std

}

綜上所述,過載賦值操作符,需要考慮鏈式賦值、自賦值和異常安全,頗為繁瑣

乙個簡化方法是,在 widget 類中宣告乙個智慧型指標

class

widget ;

此時,過載 "op=",則只需考慮鏈式賦值

widget& widget::operator=(const widget& rhs) //

copy operator=

理論上應該可行,尚未在實際專案中驗證 (留待後續測試...)

1) 過載類賦值操作符,首先考慮鏈式賦值-- 函式返回 *this,其次考慮自賦值和異常安全-- 「拷貝-交換」

2) 考慮寫乙個不拋異常的 swap 函式 (consider support for anon-throwing swap)

3) 被過載的類賦值操作符 "op="必須定義為成員函式,其它的復合賦值操作符 (如 "+=", "-=" 等)應該被定義為成員函式

4) 類中使用智慧型指標,可大大簡化過載賦值操作符 「op=」 的實現

C 過載賦值操作符

類過載賦值操作符一般都是作為成員函式而存在的,那函式應該返回什麼型別呢?參考內建型別的賦值操作,例如 int x,y,z x y z 15 賦值行為相當於x y z 15 也就是賦值操作應該返回左運算元的引用,因此,為了和內建型別相容,類中過載賦值操作符應該返回左運算元的引用,即 this,如下類a...

C 之操作符過載

1.所謂過載,就是賦予其新的意義。函式可以過載,操作符也可以過載。操作符的過載給我們的程式設計帶來了很大的便利,因為操作符只能對基本的資料型別進行操作,而對使用者自定義的類等資料結構型別不支援。因此只能對其操作符進行過載之後,才能更加方便地操作我們自定義的類物件等資料型別。但是值得注意的是並不是c ...

c 之操作符過載

include using namespace std class complex void printcom test add2 test t2 this 函式返回元素 complex operator complex c1 complex operator complex operator in...