C++-包含数组的并集

C++ - unions containing arrays

本文关键字:数组 包含 C++-      更新时间:2023-10-16

如果我有一个包含数组的C++并集。我想使用一组唯一的标识符来访问数组的每个元素。(这似乎是一件奇怪的事情。在我的应用程序中,我有一个并集,它包含指向8个方向的单元格的指针,表示某个对象如何在单元格之间移动。有时编写使用数组索引的算法很方便,但对于喜欢使用命名标识符而不是不太明显的索引的最终用户来说,这并不方便。)。)

示例:

union vector
{
    double x;
    double y;
    double data[2];
}

我相信xy"是一回事",所以实际上必须:

struct v
{
    double x, y;
}
union vector
{
    v data_v_format;
    double data_arr_format[2];
}

然后使用:

vector v1;
v1.data_arr_format[0] = v1.data_v_format.y; // copy y component to x

不幸的是,这为并集添加了一层丑陋的语法。有没有任何方法可以按照语法规定完成原始任务:

union vector
{
    double x;
    double y;
    double data[2];
}

其中x等价于data[0]y等价于data[1]

我可以写一个类来实现这一点,其中"逻辑命名的标识符变成函数,返回数组的单个组件"——但有更好的方法吗?

无论如何,即使您找到了一种方法,从非活动的并集字段读取,即不从最后一个写入的字段读取,也是UB。这实际上意味着经常看到的使用并集在4个八位字节和int之间转换IP的例子是非法的。

您可以使用访问者:

struct vec
{
    double data[2];
    double& x() {return data[0];}
    double& y() {return data[1];}
};

或者,您可以研究C++中的property实现。它将创建一个代理对象,对该对象的访问将重定向到特定的数组元素。

还有一种方法是使用引用,但这会增加结构的大小(+每个引用的指针大小):

struct vec
{
    double data[2];
    double& x = data[0];
    double& y = data[1];
};

虽然在(标准)C++中不允许,但在C中(自C11以来)您可以使用匿名结构:

// not standard C++
union vector {
    struct {
        double x;
        double y;
    };
    double arr[2];
};

一些C++编译器(包括GNU、MSVC和Clang)也支持匿名结构作为该语言的扩展。在标准C++中,您需要满足于未命名的结构:

union vector {
    struct {
        double x;
        double y;
    } data;
    double arr[2];
};

这与您的示例基本相同,因此您需要丑陋的语法层v.data.x等等。这只是更简单,因为您不需要命名内部struct;您只需要命名作为结构实例的成员。

关于你的评论:

v1.data_arr_format[0] = v1.data_v_format.y; // copy y component to x

您评论您将y复制到x。请注意,在写入v1.data_arr_format之后读取v1.x在技术上具有未定义的行为。

我告诉您,结构可能根本没有填充,因为double可能没有比它的大小更高的对齐要求,因此很可能与数组具有相同的表示。因此,在大多数实现中,这种类型的双关语可能会按预期工作,即使标准没有保证这一点。