【问题标题】:Union vs. static_cast(void*)Union 与 static_cast(void*)
【发布时间】:2011-10-31 05:27:53
【问题描述】:

我正在编写代码,直到现在我都在使用这样的结构:

struct s{
  enum Types { zero = 0, one, two };
  unsigned int type;
  void* data;
} 

我需要一些通用结构来存储来自不同类的数据,并且我想在 std::vector 中使用它,所以这就是我不能使用模板的原因。更好的选择:联合还是空指针?

Void 指针只分配我需要的空间,但由于某种原因,c++ 是强类型语言,并且在我需要使用这些数据的任何地方进行强制转换并不是 c++ 代码的设计方式。正如我所读到的,除非别无选择,否则不应使用 void 指针。

那个替代方案可能是工会。它们与 c++ 一起提供,并且为每个成员使用相同的内存空间,非常类似于 void 指针。然而,它们是有代价的——分配的空间是联合中最大元素的大小,在我的情况下,大小之间的差异很大。

这是一个相当风格和“正确使用语言”的问题,因为这两种方法都可以完成我需要做的事情,但我无法确定精美风格化的 c++ 代码是否可以弥补浪费的内存(尽管这些天的内存不是' t 一个大问题)。

【问题讨论】:

  • 如果您不想在保持安全的同时进行非严格类型检查,那么 c++ 可能不是这项工作的语言。看看 C#。
  • 您可以使用模板。只需创建一个具有所需接口的基类并存储指针。
  • @Dani 我正在编写跨平台可移植代码 + 它从另一个 c++ 库中获取许多功能,因此 C# 不是一个选择。 (不提将整个代码移植到 C# 会导致我放弃项目)
  • 您只是在现有的类型系统之上添加自己的类型系统。有什么优势?

标签: c++ void-pointers static-cast unions


【解决方案1】:

如果要存储异构类型的对象,请考虑 boost::any 或 boost::variant。

在决定使用哪一个之前,先看看比较:

希望它能帮助您做出正确的决定。从标准库中选择一个以及任何一个容器来存储对象,std::vector<boost::any>、std::vector<boost::variant> 或任何其他。

【讨论】:

  • +1 boost::any 是我需要的。但是,直到现在没有 boost 库我都很好,因为这个项目将只是另一个库,我不期待仅仅为了一个功能而依赖如此庞大的库。无论如何,很高兴知道存在这样的东西,我肯定会在我的项目中使用它们。谢谢
  • @Raven:请注意,Boost.Any 和 Boost.Variant 都是只有头文件的库,所以没有运行时依赖。 (此外,一旦您开始使用 boost,您可能会发现许多其他您想要使用的功能。)
  • @Sevis 这就是我找不到任何运行时库的原因,感谢您为我指出这一点!再次改变了我对事物的看法 -> 评论正确答案。
【解决方案2】:

boost::variant.

基本上,它是一个类型安全的联合,在这种情况下,联合似乎是迄今为止最合适的答案。可以使用 void*,但这意味着动态分配,并且您必须维护 Types enum 和用于转换的表。

内存限制可以使 void* 成为可接受的选择,但这不是“整洁”的答案,我不会选择它,直到 boost::variant 和简单的 union 都被证明是不可接受的。

【讨论】:

  • +1 表示联合更合适(与 boost:variant 匹配)
【解决方案3】:

如果您的类有足够的共同点可以放在同一个容器中,请给它们一个带有虚拟析构函数的基类,并且可能还有一个虚拟成员函数来检索您的类型代码,即使此时不仅 dynamic_cast 会更多合适,但探索您的类是否没有足够的共同点来为它们提供更完整的通用接口可能是合理的。

否则,请考虑提供具有适当类型数据成员的自定义容器类,以保存您需要放入其中的所有不同类的实例。

【讨论】:

  • +1 其实我用空指针的地方适合用接口类..编辑后看起来好多了!
猜你喜欢
  • 1970-01-01
  • 2014-05-29
  • 1970-01-01
  • 2015-05-04
  • 1970-01-01
  • 2020-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多