2013-06-18 79 views
2

您認爲在以下兩種情況下性能/內存利用率之間會有什麼區別嗎?編譯器是否會優化第一段代碼,以便兩者之間沒有任何區別。基類中的const與派生類中的static const

class VersionBase 
{ 
public: 
    VersionBase(int iVer) : m_iVersion(iVer) {…}; 
    int GetVersion() const { return m_iVersion; }; 
private: 
    const int m_iVersion;          
} 

class SomeVersionedDataObject : VersionBase 
{ 
    VersionedDataObject() : VersionBase(2) {…}; // Set version to whatever is the latest for the class 
    … 
    … 
} 

VS

class SomeVersionedDataObject 
{ 
public: 
    VersionedDataObject() 
    int GetVersion() const { return m_iVersion; }; 
private: 
    static const int m_iVersion = 2; 
} 
+0

「編譯器是否會優化第一段代碼,以便兩者之間沒有任何區別。」 - 在一些特殊構造的測試中,也許,但一般來說,你爲什麼認爲這甚至是可能的?它們並不意味着同樣的事情,並且至少,任何直接或間接依賴於sizeof(VersionBase)的行爲都會有所不同,並且* SomeVersionedDataObject的使用幾乎可以肯定地取決於sizeof( VersionBase)'。 – hvd

+0

需要注意的是,兩者總是以代碼中的常數「2」來初始化。所以問題是編譯器是否足夠聰明,可以認識到m_iVersion將爲對象的所有副本保持相同的值,因此需要一些魔力,並且不要爲每個對象副本中的變量分配內存? (再讀一遍,我想我已經得到了編譯器優化是如何工作的所有錯誤,但是沒有愚蠢的問題!) – NVM

+1

@NVM編譯器在這裏無法真正發揮魔力。 'sizeof(VersionBase)'在整個程序中必須是相同的,並且沒有任何東西阻止你直接實例化'VersionBase',並且有許多不同的'm_iVersion'值。沒有辦法將'const int'移出對象。 – Angew

回答

3

非靜態類成員,即使const,必須是類的每個對象的一部分。所以第二個定義將使用更少的內存,假設至少創建了兩個實例。

編輯

很少的內存使用和代碼口是心非一種解決方案如下:

// In one header 
template <int version> 
class VersionBase 
{ 
public: 
    int GetVersion() const { return s_version; }; 
private: 
    static const int s_version; 
}; 

template <int version> 
const int VersionBase::s_version = version; 


// Anywhere, using the header above 
class SomeVersionedDataObject : public VersionBase<2> 
{ 
    ::: 
}; 
+0

假設我將有成千上萬的'SomeVersionedDataObject'實例和從VersionBase派生的多個類(總是由一個常量值初始化,這個常量值對於特定類的所有實例都是相同的),是否有一種設計方法可以使每個對象一個特定的類不爲變量分配內存? – NVM

+0

@NVM是的,使用第二個例子中的static const變量。 – Angew

+0

謝謝,但那樣會非常醜陋和不可維護(我有數百個這樣的類)。我將不得不在所有版本類中重複相同的一段代碼。我知道你已經回答了我的問題,只是想看看有沒有辦法解決這個問題。 – NVM

1

有自己處理系列化公平一點,我在不同的東西結算(扔繼承窗外):

inline int version(SomeVersionedDataObject const&) { return 2; } 

內存佔用量相當於static int const version的情況,除了version方法的實現可以自由地更聰明一些(即,你可以擁有派生到virtual方法的多態類的版本,...)。

和當然,它很容易爲那些對象的默認版本,不需要一個尚未:

int version(...) { return 0; } 

起來我更喜歡在一些基礎類的編碼信息,因爲我可以擴展任何類與它沒有修改類本身

+0

這實際上是一個絕妙的主意。我想到的問題之一是派生類擁有自己的版本號,繼承將是一個問題。這將在那裏工作。 – NVM