1

给定一个这样的模板类:

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),所以我现在的问题是:是否已经有一些标准的空类我应该用于这使我的代码更具可读性?

4

5 回答 5

5

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

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

template<>
class C<NoData> {
   // Do not declare that member
};
于 2012-04-18T11:39:37.453 回答
3

好的,我发现空类是迄今为止我能得到的最接近的,所以我现在的问题是:是否已经有一些标准的空类我应该使用它来使我的代码更具可读性?

不,您可以自己定义一个:

struct standard_empty_class {};

用它。

所以基本上,如果用户想要存储额外的数据,他将构建C<MyAdditionalData>,但如果他不这样做,它应该就像C<NoData>并且不会有数据。

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

于 2012-04-18T11:20:46.613 回答
2

我不认为这是可能的。实际上,情况恰恰相反。即使是空类在实例化时也会占用内存(一个字节),因此程序在实例之间可能会有所不同。那是

class A {
};

A a, b;  // vars of type A

然后a并且b必须占用一些内存,以便您的程序可以引用它们,例如if (a == b). 如果他们不使用内存,您将无法做到这一点。

于 2012-04-18T11:21:15.797 回答
2

没有数据成员,因为对象的大小永远不会为零,并且数据成员没有退出子句。

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

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不存在而绊倒,所以任何使用它的成员函数都不会编译 for 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

于 2012-04-18T12:27:43.973 回答
1

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

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

使用 typedef 以获得更好的清晰度:

typedef C<int> CEmptyGraphNode;
于 2012-04-18T12:04:10.240 回答