2015-01-10 55 views
8

我想定义一个结构,例如type,这样sizeof(type)不小于某个值。用最小尺寸定义结构

动机:

我有一个矢量std::vector<type>,我会从中删除某些元素。另外,我已经将某些元素的索引保存到其他地方,因此我希望将其标记为未使用并在将来重用。这导致我将下一个可用位置保存为已删除位置中的列表。因此,sizeof(type)应该不小于sizeof(size_t)type也应该正确对齐。

可能的解决方案:

  1. boost::variant<type, size_t>

    这有从我的角度来看两个问题。如果我use boost::get<type>,性能将显着下降。如果我使用boost::apply_visitor,则语法会很奇怪,并且根据我的配置文件,性能也会下降。

  2. union{type t; size_t s;}

    当然这个工程除了两个不足。首先,引用type成员的语法会更加混乱。其次,我必须为此联合定义构造函数,复制构造函数等。

  3. 通过char[sizeof(size_t) - sizeof(type)]

    扩展type这几乎满足了我的要求。然而,这个风险是零长度数组,这是C++标准不支持的,并且可能是错误的对齐。

因为我不会用type作为size_t的时候,我想只是保证在需要的时候,我可以使用reinterpret_cast<size_t>

补语

阅读评论之后,我觉得我的问题的最佳解决方案应该是boost::variant。但我仍然想知道是否有办法结合解决方案2和3的优点,即:

a。我可以在不更改的情况下访问type的会员。

b。获得reinterpret_cast<size_t>工作的保证。

+0

非常漂亮制定问题。 +1。但在我看来,问题的根源在于你保存了索引以备将来使用。我认为你应该考虑一些不涉及这种恶意元素的向量中的一些元素作为向量中的下一个有效索引。 – bolov

+0

@bolov我同意你的意见。我在向量中使用了unique_ptr ,并保存了类型*。但我更喜欢直接访问类型。 (它不适合生产使用)事实上,我认为boost :: variant可能是我的最终解决方案,但我期待着更好的解决方案。 – cqdjyy01234

+0

你为什么想象boost :: variant会带来性能成本? –

回答

3

可以减轻有关解决方案3的关注的东西,如:

struct data 
{ 
    // ... 
}; 

template<class T, bool> class pad_; 
template<class T> class pad_<T, true> { char dummy[sizeof(T) - sizeof(data)]; }; 
template<class T> class pad_<T, false> {}; 

template<class T> using pad = pad_<T, (sizeof(T) > sizeof(data))>; 

class type : public data, pad<size_t> 
{ 
    // ... 
}; 

此代码:

  • 假定empty base optimization使pad可以完全type布局优化出来的时候sizeof(data) >= sizeof(size_t)
  • 具有零长度阵列的不危险
+0

这看起来很棒最后一个问题是,如果用作size_t,是否存在对齐问题? – cqdjyy01234

+0

对于对齐,您应该添加['alignas'](http:// en .cppreference.com/w/cpp/language/alignas)说明符转换为'type'定义(C++ 11)或者使用['union']尝试(http://stackoverflow.com/questions/11214632/alignment-guarantees -of-static-char-array)。所有这些都是非常棘手的问题,我不确定这是不是值得的。 – manlio

1

虽然这是一个有趣的问题设计本身接缝怀疑。

  1. 当插入一个新元素时,标记为未使用的项目在生成向量之前首先被考虑。这意味着项目的相对顺序是不可预测的。如果这是可以接受的,你可以使用一个(智能)指针向量。

    通常除去从中间项目时的载体是低效的。由于顺序无关紧要,可以将正在移除的元素与最后一个元素交换并弹出最后一个元素。

  2. 所有元素的大小相同;使用池分配它们可能会比使用系统分配器更快。

    一个池基本上以大块分配内存,并根据请求提供较小的块。池通常将未使用的列表存储在尚未分配的块中以跟踪可用内存(问题中所述的相同想法)。有一些很好的实现(来自Boost和其他来源)。

  3. 关于原始设计,枚举矢量中的元素很麻烦,因为真实元素与“孔”混合在一起,逻辑将被额外的检查混淆。

在原始设计背后可能存在一些推销原因;不幸的是@ user1535111没有告诉细节。

+0

没错,这个设计是有问题的!我会回到指针。问的问题,所以我选择manlio的答案! – cqdjyy01234