是否有可能声明一个不占用内存的成员变量?

时间:2012-04-18 11:10:40

标签: c++ class templates member

给出这样的模板类:

template <typename T>
class C
{
T member;
//... some other members that are not of interest here
};

我可以提供任何类型的T来阻止member占用不必要的内存吗? 起初void突然出现在我的脑海中,但我知道您无法声明void的变量。


当然,这个例子是简化的。后台是一个包含一些信息的类,但可以获取用户添加的其他信息。当用户不想添加其他信息时,应该可以将其删除。所以基本上如果用户想要存储其他数据,他将构建C<MyAdditionalData>,但如果他不这样做,它应该像C<NoData>那样,并且没有数据。当然,我可以写一些模板专业化,但我不喜欢写两次。

修改
好吧,我发现一个空类是我能得到的最接近的(由于对齐,仍然消耗1个字节甚至4/8),所以现在我的问题是: 我是否应该使用一些标准的空类来使我的代码更具可读性?

5 个答案:

答案 0 :(得分:5)

为类型NoData专门化您的模板类,并且不要在此专业化中定义成员。

template <class T>
class C {
   T member;
...
};

template<>
class C<NoData> {
   // Do not declare that member
};

答案 1 :(得分:3)

  

好的,我发现一个空类是我到目前为止最接近的,所以现在我的问题是:我是否应该使用一些标准空类来制作我的代码更具可读性?

没有。您可以自己定义一个:

struct standard_empty_class {};

使用它。

  

所以基本上如果用户想要存储其他数据,他将构建C<MyAdditionalData>,但如果不存在,则应该像C<NoData>那样,并且没有数据。

我不明白这一点。如果用户不想存储任何数据,那么为什么即使你需要一个类,仍然需要编写C<NoData>?忘了那个案子。没有数据意味着没有课程。它解决不了吗?

答案 2 :(得分:2)

我不认为这是可能的。实际上,这是另一种方式。即使空类在实例化时占用内存(一个字节),因此程序可以在实例之间有所不同。那是

class A {
};

A a, b;  // vars of type A

然后ab必须占用一些内存,以便您的程序可以引用它们,例如if (a == b)。如果他们不使用记忆,你就不能这样做。

答案 3 :(得分:2)

使用数据成员no,因为对象永远不会为零,并且数据成员没有get-out子句。

但是,如果基类子对象为空,则其大小为零。因此:

template <typename T>
struct Member {
    T member;
};

template <>
struct Member<void> {
};

template <typename T>
class C : private Member<T>
{
//... some other members that are not of interest here
};
我想,

应该有效。但是你可能会因为C<void>::member不存在这一事实而绊倒,因此任何使用它的成员函数都不会为C<void>编译,包括构造函数。

  

如果用户想要存储他将构建的其他数据   C<MyAdditionalData>

为什么没有C非模板类而没有其他数据成员,如果用户想要添加数据成员,请使用C作为基类?记得给C一个受保护的析构函数 - 每个基类都应该有受保护的析构函数或虚拟析构函数,但由于你的C模板类没有虚拟析构函数,所以不需要非模板版本也是虚拟的。

沿着这些方向,您可以这样做:

class CNoData
{
//... some other members that are not of interest here
};

template <typename T>
class CWithData<T> : CNoData
{
T member
// have to duplicate constructors, unfortunately.
};

如果你真的需要它,添加一个类型特征:

template <typename T>
struct C {
     typedef CWithData<T> type;
};

template <>
struct C<void> {
    typedef CNoData type;
};

然后你会写C<MyAdditionalData>,现在你写CWithData<MyAdditionalData>,你写C<some_type_that_might_be_void>的地方就写typename C<some_type_that_might_be_void>::type

答案 4 :(得分:1)

正如您所说,模板已包含一些其他数据。它有虚拟方法,那就是另一个成员。

添加一个额外的成员是一个非常小的开销,可以简单地忽略,所以我只使用C.(如果有其他成员小于对齐,甚至是char)

使用typedef更清晰:

typedef C<int> CEmptyGraphNode;