4

工会不是我经常使用的东西,在这里查看了一些关于它们的其他问题之后,似乎几乎总是有某种警告,它们可能不起作用。例如。结构可能具有意外的填充或字节序差异。

在我正在使用的数学库中遇到了这个问题,我想知道它是否完全安全。我假设多维数组没有任何额外的填充,并且由于两个定义的类型相同,它们保证占用完全相同的内存量?

template<typename T> class Matrix44T
{
    ...

    union
    {
        T M[16];
        T m[4][4];
    } m;
};

这种设置有什么缺点吗?定义的顺序会对它的工作方式产生什么影响吗?

4

3 回答 3

5

虽然我在我的 Matrix 类中做的完全一样,但我认为这取决于实现,请阅读标准:

标准 9.5.1:

在一个联合中,任何时候最多有一个数据成员处于活动状态,即任何时候最多可以有一个数据成员的值存储在一个联合中。[注意:为了简化联合的使用,做了一个特殊的保证:如果一个 POD 联合包含多个共享一个公共初始序列的 POD 结构(9.2),并且如果这个 POD 联合类型的对象包含以下之一POD-structs,允许检查任何 POD-struct 成员的公共初始序列;见 9.2。]

然后的问题是做mM共享一个共同的初始序列,要回答这个问题,我们看一下 9.2/15:

如果两个 POD 联合(第 9 条)类型具有相同数量的非静态数据成员,并且相应的非静态数据成员(以任何顺序)具有布局兼容类型(3.9),则它们是布局兼容的。

阅读完这篇文章后,答案似乎是,严格意义上来说,不兼容m并且不兼容布局。M

实际上,我认为这在所有编译器上都可以正常工作。

于 2010-05-21T10:22:14.800 回答
1

如果您遵守规则,填充和字节序差异不会伤害您。

看看这段代码

union { int a; float b; } wrong;

wrong.a = 1;
printf("%f", wrong.b);

这是错误的,因为如果你写了成员“a”,那么除了“a”之外的任何读取都是未定义的。

总而言之:无法判断工会是否安全。不安全的不是定义,而是它的使用方式。

于 2010-05-21T10:10:03.037 回答
0

union不,根据您的假设,这似乎很好用。

我会选择更好的名字而不是mM但除此之外,它是一个很好的用法union

于 2010-05-21T10:02:27.870 回答