**於《劍指offer》
題目:如下為型別cmystring的宣告,請為該型別新增賦值運算子函式
class cmystring;
當面試官要求應聘者定義乙個賦值運算子函式時,他會在檢查應聘者寫出的**時關注如下幾點:
(1)是否把返回值的型別宣告為該型別的引用,並在函式結束前返回例項自身的引用(*this)。只有返回乙個引用,才可以允許連續賦值。否則,如果函式的返回值是void,則應用該賦值運算子將不能進行連續賦值。假如有3個cmystring的物件:str1,str2,str3,在程式中語句str1=str2=str3將不能通過編譯。
(2)是否把傳入的引數型別宣告為常量引用。如果傳入的引數不是引用而是例項,那麼從形參到實參會呼叫一次複製建構函式。把引數宣告為引用可以避免這樣的無謂消耗,能提高**的效率,同時,我們在賦值運算子函式內不會改變傳入的例項的狀態,因此應改為傳入的引用引數加上const關鍵字。
(3)是否釋放例項自身已有的記憶體。如果我們忘記在分配新記憶體之前釋放自身已有的空間,則程式將出現記憶體洩露。
(4)判斷傳入的引數和當前的例項(*this)是不是同乙個例項。如果是同乙個,則不進行賦值操作,直接返回。如果事先不判斷就進行賦值,那麼在釋放例項自身記憶體的時候就會導致嚴重的問題:當*this和傳入的引數是同乙個例項時,一旦釋放了自身記憶體,傳入的引數的記憶體也同時被釋放了,因此再也找不到需要賦值的內容了。
經典的解法,適用於初級程式設計師
當我們完整地考慮了上述4個問題之後,可以寫出如下的**:
cmystring& cmystring::operator=(const cmystring &str)delete m_pdata;
m_pdata=nullptr;
m_pdata=new char[strlen(str.m_pdata)+1];
strcpy(m_pdata,str.m_pdata);
return *this;
}
考慮異常安全性的解法,高階程式設計師必備
在前面的函式中,我們在分配記憶體之前先用了delete釋放了例項m_pdata的記憶體。如果此時內不足導致new char 丟擲異常,則m_pdata將會是乙個空指標,這樣非常容易導致程式崩潰。也就是說,一旦在賦值運算子函式內部丟擲乙個異常,cmystring的例項不再保持有效狀態,這就違背了異常安全性原則。
要想在賦值運算子函式中實現異常安全性,我們有兩種方法。一種簡單的方法是我們先用new 分配新內容,再用delete釋放已有的內容。這樣只在分配內容成功之後再釋放原來的內容,也就是當分配失敗時我們能確保cmystring的例項不會被修改。我們還有一種更更好的方法,即先建立乙個臨時例項,再交換臨時例項和原來的例項。下面是這種思路的參考**:
cmystring& cmystring::operator=(const cmystring &str)return *this;
}
在這個函式中,我們先建立乙個臨時例項strtemp,接著把strtemp.m_pdata和例項自身的m_pdata進行交換。由於strtemp是乙個區域性變數,但程式執行到if的外面時也就出了該變數的作用域,就會自動呼叫strtemp的析構函式,把strtemp.m_pdata所指的記憶體釋放掉。由於strtemp.m_pdata指向的記憶體就是例項之前m_pdata的記憶體,這就相當於自動呼叫析構函式釋放例項的記憶體。
在新**中,我們在cmystring的建構函式裡用new 分配記憶體。如果由於記憶體不足丟擲諸如bad_alloc等異常,但我們還沒有修改原來例項的狀態,因此例項的狀態還是有效的,這也就保證的異常的安全性。
面試題1 賦值運算子函式
面試題1 為如下cmysting的宣告,新增賦值運算子函式。class cmystring 注意事項 1.是否把返回值型別宣告為該型別的引用,並在函式結束前返回例項自身的引用 即 this 2.是否把傳入的引數的型別宣告為常量引用。3.是否釋放例項自身的記憶體。4.是否判斷傳入的引數和當前的例項是不...
面試題1 賦值運算子函式
面試題1 為如下cmysting的宣告,新增賦值運算子函式。class cmystring 注意事項 1.是否把返回值型別宣告為該型別的引用,並在函式結束前返回例項自身的引用 即 this 2.是否把傳入的引數的型別宣告為常量引用。3.是否釋放例項自身的記憶體。4.是否判斷傳入的引數和當前的例項是不...
面試題1 賦值運算子函式
題目 如下型別為cmystring的宣告,請為該型別新增賦值運算子函式。class cmystring 賦值運算子 函式 cmystring cmystring operator const cmystring str 當記憶體不夠時,new char會丟擲異常,分配記憶體失敗,m pdata將是乙...