C 中過載 操作符的正確方法

2021-05-04 03:35:48 字數 1454 閱讀 8753

使用者定義的型別,如:字串,日期,複數,聯合體以及檔案常常過載二元 + 操作符以實現物件的連線,附加或合併機制。但是要正確實現 + 操作符會給設計,實現和效能帶來一定的挑戰。本文將概要性地介紹如何選擇正確的策略來為使用者定義型別過載這個操作符。

考慮如下的表示式: int x=4+2;

內建的 + 操作符有兩個型別相同的運算元,相加並返回右值 6,然後被賦值給 x。我們可以斷定內建的 + 是乙個二元的,對稱的,可交換的操作符。它產生的結果的型別與其運算元型別相同。按照這個規測,當你為某個使用者定義型別過載操作符時,也應該遵循相應內建操作符的特徵。

為使用者定義型別過載 + 操作符是很常見的程式設計任務。儘管 c++ 提供了幾種實現方法,但是它們容易使人產生設計上的誤解,這種誤解常常影響**的正確性,效能以及與標準庫元件之間的相容性。

下面我們就來分析內建操作符的特徵並嘗試模仿其相應的過載機制。

第一步:在成員函式和非成員函式之間選擇

你可以用類成員函式的方式實現二元操作符如:+、- 以及 ==,例如:

class string

;這個方法是有問題的。相對於其內建的操作符來說,過載的操作符在這裡不具有對稱性;它的兩個引數乙個型別為:const string * const(這個引數是隱含的),另乙個型別為:const string &。因此,一些 stl 演算法和容器將無法正確處理這樣的物件。

另外乙個可選方法是把過載操作符 + 定義為乙個外部(extern)函式,該函式帶兩個型別相同的引數:

string operator + (const string & s1, const string s2);

這樣一來,類 string 必須將該過載操作符宣告為友元: 

class string

;第二步:返回值的兩難選擇

如前所述,內建操作符 + 返回右值,其型別與運算元相同。但是在呼叫者堆疊裡返回乙個物件效率很低,處理大型物件時尤其如此。那麼能不能返回乙個指標或引用呢?答案是不行。因為返回指標破壞引數型別與返回值型別應該相同的規則。更糟的是,鏈結多個表示式將成為不可能:

string s1,s2,s3;

string res;

res=s1+s2+s3; // 不可能用 string* 作為返回值

雖然有乙個辦法可以定義額外的 + 操作符過載版本,但這個辦法是我們不希望用的,因為返回的指標必須指向動態分配的物件。這樣的話,如果呼叫者釋放(delete)返回的指標失敗,那麼將導致記憶體洩漏。顯然,返回 string* 不是乙個好主意。

那麼返回 string& 好不好呢?返回的引用必須一定要是乙個有效的 string。它避免了使用動態物件分配,該方法返回的是乙個本地靜態物件的引用。靜態物件確實解決了記憶體洩漏問題,但這個方法的可行性仍然值得懷疑。在乙個多執行緒應用中,兩個執行緒可能會併發呼叫 + 操作符,因此造成 string 物件的混亂。而且,因為靜態物件總是保留其呼叫前的狀態,所以有必要針對每次 + 操作符的呼叫都清除該靜態 string 物件。由此看來,在堆疊上返回結果仍然是最安全和最簡單的解決方案。

C 中過載 操作符的正確方法

使用者定義的型別,如 字串,日期,複數,聯合體以及檔案常常過載二元 操作符以實現物件的連線,附加或合併機制。但是要正確實現 操作符會給設計,實現和效能帶來一定的挑戰。本文將概要性地介紹如何選擇正確的策略來為使用者定義型別過載這個操作符。考慮如下的表示式 int x 4 2 內建的 操作符有兩個型別相...

C 中過載 操作符的正確方法

使用者定義的型別,如 字串,日期,複數,聯合體以及檔案常常過載二元 操作符以實現物件的連線,附加或合併機制。但是要正確實現 操作符會給設計,實現和效能帶來一定的挑戰。本文將概要性地介紹如何選擇正確的策略來為使用者定義型別過載這個操作符。考慮如下的表示式 int x 4 2 內建的 操作符有兩個型別相...

C 中過載 操作符的正確方法

編譯 mtt 工作室 原文出處 overloading operator the right way 摘要 本文概要性地介紹如何選擇正確的策略來為使用者定義型別過載 操作符。使用者定義的型別,如 字串,日期,複數,聯合體以及檔案常常過載二元 操作符以實現物件的連線,附加或合併機制。但是要正確實現 操...