本篇文章的關注點是引用作為函數返回值,網上類似很多,具體可參考引用作為函數返回值的優缺點。這里,我想寫下自己的想法。
在C++中,引用變量必須要初始化,否則會有編譯錯誤。這里指的初始化,一般變量賦值初始化。如果是通過函數返回值來初始化,那就要好好考慮下。
以獲取字體信息場景為例子:在啟動時,通過讀取字體配置文件來獲得字體信息,保存在m_vLogFont。外部通過GetFont接口函數來獲得字體信息,每一個Id對於一種字體,接口函數大致實現如下:
const LOGFONT& GetFont(int nFontId)
{
if (nFontId < m_vLogFont.size())
{
return m_vLogFont[nFontId];
}
}
// 外部使用
const LOGFONT& FontInfo = GetFont(FONT_ID);
問題一:通過函數返回值來定義的引用,如何判斷其有效性?
按照以往的知識,引用變量一旦初始化,之后就不能再改變。通過函數返回值也算是初始化,在這種情況下,如果引用無效,比如傳入一個很大的FontId,在編譯階段是無法發現錯誤,只有在運行階段,會報讀取訪問沖突的錯誤。
解答:這種情況下,在編譯期間是無法判斷其有效性的,在運行時可判斷。
問題二:如果出現上面的情況,如何預防?
這里有兩種解決方案,以GetFont為例子:
-
在if的else分支中,加上ASSERT斷言,在調試階段發現問題。
-
在if的else分支中,加上出錯處理,即獲取不到,則返回默認字體信息。
這兩種處理方式,在實踐中都有應用,不同方式對應的場景不一。比如,第二種方式的應用場景是字體配置信息異常。如果不這么做,會因一處配置信息異常,導致整個軟件無法運作。
解答:如果產品人員有這方面的需求考慮或者之前有類似情況發生,這種處理方式就是合理的。否則,推薦第一種方式。
小結:工具類函數的返回值需要仔細考慮異常情況,盡量做到異常情況對外部暴露,由外部去處理。同時,此類函數注釋撰寫要規范,不要注釋說明和內部實現不一致,給使用者和后來者挖坑。