2013-06-18 43 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