11

如果我有这个怎么办:

union{
    vector<int> intVec ;
    vector<float> floatVec ;
    vector<double> doubleVec ;
} ;

当然,我将只使用 3 个向量中的一个。但是......当所有 3 个向量都被构造时会发生什么?
3个向量的构造函数会相互干扰吗?(因为它们3在同一个内存地址中)

谢谢。

4

6 回答 6

16

当前的 C++ 标准不允许在联合中使用非 POD 类型。您将从以下位置收到此编译器错误gcc

error: member ‘std::vector<int, std::allocator<int> >
<anonymous union>::i’ with constructor not allowed in union
error: member ‘std::vector<int, std::allocator<int> >
<anonymous union>::i’ with destructor not allowed in union

新的 C++ 标准 ( C++0x ) 提出了不受限制的联合,但它给 C++添加了更多的对象生命周期陷阱

于 2009-04-12T08:48:25.697 回答
9

您不能拥有包含非 POD 类类型的联合。您的示例将无法编译。

您可以将boost::variant其用作 C 联合的安全替代方案。请参阅boost.org 上的文档。但是,您可能会重新考虑您的设计并改用多态性。当然,这取决于您要完成的工作。

于 2009-04-12T08:48:37.973 回答
2

来自 C++ 标准,第 9.5 节:

具有非平凡构造函数 (12.1)、非平凡复制构造函数 (12.8)、非平凡析构函数 (12.4) 或非平凡复制赋值运算符 (13.5.3, 12.8) 的类的对象不能成为工会成员,

在这里,对于“非平凡”阅读“有用”:-)

于 2009-04-12T08:52:02.927 回答
2

3个向量的构造函数会相互干扰吗?(因为它们3在同一个内存地址中)

C++ 标准不允许你的程序,所以它(充其量!)实现定义发生了什么。

例如,如果您的实现调用所有三个默认构造函数,并且它们都分配内存,并存储指向新分配空间的指针,那么您就有内存泄漏(前两个分配被第三个覆盖)。

如果析构函数都被调用并且它们都释放了“他们的”内存,那么您将进行双重释放(实际上是三重释放);这可能会破坏分配数据结构,这是一件坏事。如果你崩溃了,你会很高兴,因为如果你不崩溃,调试起来会困难得多。

我认为这些问题可能是标准不允许这样做的原因。

(更有意义的事情可能是只默认构造第一类,但这仍然不明智,只是不那么疯狂......)

于 2009-04-12T08:55:05.773 回答
2

现在 C++ 标准支持变体。检查https://en.cppreference.com/w/cpp/utility/variant

std::variant

在标题中定义

template <class... Types>   
class variant;

(C++17 起)

类模板std::variant代表一个类型安全的union。在任何给定时间的实例std::variant要么保存其替代类型之一的值,要么在错误的情况下 - 没有值(这种状态很难实现,请参阅valueless_by_exception)。

与联合一样,如果变体拥有某个对象类型 T 的值,则 T 的对象表示直接分配在变体本身的对象表示中。不允许变体分配额外的(动态)内存。

不允许变量包含引用、数组或 void 类型。空变体也是格式错误的(std::variant<std::monostate>可以代替使用)。

一个变体被允许多次持有相同的类型,并且持有相同类型的不同的 cv 限定版本。

与聚合初始化期间联合的行为一致,默认构造的变体保留其第一个替代的值,除非该替代不是默认构造的(在这种情况下,变体也不是默认构造的)。辅助类std::monostate可用于使此类变体默认可构造。

于 2019-08-26T05:12:05.260 回答
1

您可能想看看Boost.Variant可以包含不同类型的单个值。

于 2009-04-12T08:52:09.010 回答