Jer*_*ner 7 c++ static templates member-variables
我有一个模板化的容器类,类似于这个玩具代码:
template <class ItemType> class MyVector
{
public:
MyVector() : _numItems(0), _items(NULL) {/* empty */}
/** Returns a reference to the first item in our array,
* or a default-constructed item if the array is empty.
*/
const ItemType & GetFirstItemWithDefault() const
{
return (_numItems > 0) ? _items[0] : _defaultItem;
}
[other methods omitted because they aren't relevant]
private:
int _numItems; // how many valid items (_items) points to
ItemType * _items; // demand-allocated
const ItemType _defaultItem;
};
Run Code Online (Sandbox Code Playgroud)
这个类非常方便使用 - 任何代码都可以#include"MyVector.h",然后开始声明MyVector和MyVector等类型的对象,并且所有Just Works(tm)都没有任何需要的东西.
然而,有一件事困扰我的是_defaultItem成员变量的存在,这只是为了让GetFirstItemWithDefault()能够在容器为空时返回有效的引用.反对意见是,如果我声明N MyVector对象,这意味着_defaultItem的N个副本也将出现在RAM中 - 即使它们都是相同且只读的,因此实际上只需要其中一个过程,而不是每个MyVector一个.
因此,显而易见的解决方案是将_defaultItem设为静态....但AFAICT带有成本:如果我这样做,任何旧代码都不再可能只需#include"MyVector.h"就可以了. ..现在用户必须确保在他的一个.cpp文件中为该静态变量声明存储,这是(a)屁股的痛苦,并且(b)意味着代码的用户必须知道该类的内部实现的细节.由于_defaultItem是一个私有成员变量,因此该类的用户不应该考虑它,甚至不应该意识到它存在,更不用说知道他需要为它声明存储.(如果两个独立的代码段都为它声明存储,每个不知道另一个已经做了同样的事情怎么办?这不会导致重复符号链接器错误吗?)
因此,我的问题是:有没有办法告诉C++为这个静态成员变量自动提供一个唯一的存储(每个实例化类型的MyVector),以便MyVector的用户不必知道它?(请注意,对于MyVector <...>的所有可能实例化,它都需要是自动的,而不仅仅是针对少数常见情况)
为什么不将该默认项目设为静态本地函数?
const ItemType & GetFirstItemWithDefault() const
{
static const ItemType _default;
return (_numItems > 0) ? _items[0] : _default;
}
Run Code Online (Sandbox Code Playgroud)
如果你想再次检查某个其他函数中的默认项目,这可能不是你想要的,但为此你可以把它放在一个单独的函数中(也可能是静态的):
static const ItemType& GetDefault() const
{
static const ItemType _default;
return _default;
}
Run Code Online (Sandbox Code Playgroud)
并在需要访问默认项目时调用该函数.
也就是说,我认为有一个默认项目并不是很好.std::vector也没有它,也不需要它.只需告诉用户检查矢量是否empty完成.隐藏静力学的一个问题是,你不知道ItemType.它可能是一个吃掉大量资源的类,你只是做了另一个例子!也许重新考虑一下这个课程的设计,之后再换一个std::vector.:)
如果它是模板,编译器将为您发挥作用。只需将静态成员放在标头中,编译器就会发现它仅被实例化一次。
template <class ItemType>
class MyVector
{
public:
//...
private:
static const ItemType _defaultItem;
};
template <class ItemType>
const ItemType MyVector<ItemType>::_defaultItem;
Run Code Online (Sandbox Code Playgroud)