【问题标题】:How to make STL pair with one type an "empty struct" only take up the space of the other type?如何使 STL 与一种类型的“空结构”配对只占用另一种类型的空间?
【发布时间】:2012-12-04 17:04:49
【问题描述】:

我正在处理需要键和值类型的模板化键/值存储类,并将它们在内部存储为std::pair。然而,我发现了一个我只想存储一个键并且仍然利用这个类的索引的情况。我需要完全重构这个东西以只处理一个键而不是键/值对(或浪费大量空间),所以我想知道是否有办法让 std::pair 对象采用空结构(或其他),并且只占用与配对中其他类型相同的空间。

我试过了:

struct EmptyStruct
{
};

然后运行这个:

typedef std::pair<int, EmptyStruct> TestPair;
std::cout << sizeof(TestPair) << " vs " << sizeof(int) << "\n";

但是得到了这个输出:

8 vs 4

在 VC++ 2012 中的“发布”模式下启用优化,包括 /O1“最小化大小”。

有没有办法让结构在 std::pair 的上下文中被视为“无大小”?

【问题讨论】:

  • 您也可以从相反的方向解决这个问题,将存储类分解并提供两个接口,一个带有 (key,value),另一个只带有 (key)。这是标准库实现中的常用方法,其中std::mapstd::set 使用相同的底层平衡树实现,每个都有不同的value_type 和比较器。
  • 请注意,“最小化大小”不会改变对象的大小,它只会影响生成的代码的大小。类型内部的空间优化必须在库级别完成。
  • 正如我在 ChrisW 的回答中提到的,您可以尝试改用 std::tuple,这样可以删除空类型所需的空间。不过,这取决于实施的质量。因为 VS2012 没有正式的可变参数模板(但请查看 Nov 2012 CTP!),它的 std::tuple 实现已经投入了大量资金。

标签: c++ data-structures


【解决方案1】:

std::pair 无法做到这一点,而 Boost compressed_pair 则无法做到这一点。

在您着手编写自己的完全符合压缩的pair 模板之前,请注意这比看起来更难。

【讨论】:

  • 您的链接似乎已损坏。
【解决方案2】:

有没有办法让结构在 std::pair 的上下文中被视为“无大小”?

否:因为一个类的单独实例必须具有不同/可区分的地址......所以有一个最小(非零)大小。

【讨论】:

  • 这是 true,但我将问题解读为“std::pair/std::tuple 的实现是否不会为空类类型提供任何开销?”我认为答案是肯定的。使用空基优化,应该可以这样做(我记得 Howard Hinnant 给出了一个演示实现,IIRC。)
  • @GManNickG AFAIK libstdcpp 为tuple 执行空对象优化,但我从未见过它配对。
  • @GManNickG:有趣的是你提出了std::tuple,在这种情况下,标准允许(IIRC)这种优化,但在std::pair的情况下,这不是一个选项。
  • @pmr(和大卫):呃,对。我说std::pair 会这样做有点傻,不是吗? :)
  • 供参考,this is what I was referring to when I mentioned the EBO for tuple。 @pmr:是的,需要某种程度的间接性。但是std::pair::firststd::pair::second 直接引用成员,所以空类必须存在于某处(占用空间)。
【解决方案3】:

std::pair 无法做到这一点,但创建自己的结构相当容易 - compressed_pair 这样做:如果任一类型为空,只需专门化模板以仅容纳一个成员。

有一个库——SeqAn——它有such a type

【讨论】:

    【解决方案4】:

    如果第二种类型是EmptyStruct,您可以专门化pair 以不实际存储价值

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-01-15
      • 2020-12-30
      • 2018-06-04
      • 1970-01-01
      • 2011-08-10
      • 1970-01-01
      • 2021-09-07
      相关资源
      最近更新 更多