2012-07-07 89 views
3

在有效的C++到對象(項目18:使接口易於正確使用,而難以錯誤地使用),我看到類似於以下一個代碼示例:返回靜態const引用從功能

class Month 
{ 
public: 
    static Month Jan() 
    { 
     return Month(1); 
    } 

    static Month Feb() 
    { 
     return Month(2); 
    } 

    //... 

    static Month Dec() 
    { 
     return Month(12); 
    } 

private: 
    explicit Month(int nMonth) 
     : m_nMonth(nMonth) 
    { 
    } 

private: 
    int m_nMonth; 
}; 

Date date(Month::Mar(), Day(30), Year(1995)); 

是否有更改函數的任何缺點,以便它們將靜態常量引用返回給Month?

class Month 
{ 
public: 
    static const Month& Jan() 
    { 
     static Month month(1); 
     return month; 
    } 

    static const Month& Feb() 
    { 
     static Month month(2); 
     return month; 
    } 

    //... 

    static const Month& Dec() 
    { 
     static Month month(12); 
     return month; 
    } 

private: 
    explicit Month(int nMonth) 
     : m_nMonth(nMonth) 
    { 
    } 

private: 
    int m_nMonth; 
}; 

我以爲第二個版本比第一個版本更高效。

+1

_primary_的事情是你的代碼在C++ 03中不是線程安全的,只符合C++ 11編譯器。 – ildjarn 2012-07-07 15:33:43

回答

6

原因1:不是更好。

按值返回會產生複製整個對象的代價。

通過引用返回會導致複製有效指針的成本以及取消引用該指針的成本。

由於Monthint的大小:

  • 複製基準速度不
  • 非關聯仍然會發生

所以在一般情況下,通過const引用返回是一種優化選擇來防止這將是一個昂貴的副本。

原因2:static使情況變得更糟

不同於C,C++承諾,在函數中的靜態變量將在該函數的第一呼叫的時間來構成。

實際上,這意味着每次調用函數都必須以一些看不見的邏輯開始,以確定它是否是第一次調用。

又見沃恩卡託的答案

又見ildjam的評論

+0

因此,僅當對象的大小大於原始數據類型時才返回對象的引用才更有效率? – Blood 2012-07-07 15:31:09

+0

如果Month類中有其他成員變量,該怎麼辦? – jpen 2012-07-07 15:35:08

+0

@DrewDormann okey,謝謝。現在很明顯:) +1 – Blood 2012-07-07 15:39:56

2

一些編譯器將包含靜態局部變量和內聯是這裏最重要的性能優化不聯方法。

+0

「內聯是這裏最重要的性能優化。」是嗎?我並不反對,我真的不知道。有關於此的更多信息? – marsh 2016-08-24 12:03:58

+1

@marsh:這是基於我的經驗。由於個別月份函數基本上返回一個常量,因此編譯器有很多機會利用內聯。例如,如果您正在進行日期計算,則可以在編譯時計算結果,而不是運行時。 – 2016-08-24 12:40:15

+0

我沒有想到在編譯時計算結果。好想法。 – marsh 2016-08-24 12:58:05