C ++ - 包含数组的联合

时间:2015-12-14 13:53:21

标签: c++ class struct unions

如果我有一个包含数组的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]

我可以编写一个类来执行此操作,其中"逻辑命名的标识符成为函数,返回数组的单个组件" - 但有更好的方法吗?

2 个答案:

答案 0 :(得分:3)

无论如何,即使你会找到一种方法,从非活动的联合字段读取,即不是从最后写入的字段读取,是UB。这实际上意味着经常看到的使用union在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];
};

答案 1 :(得分:1)

虽然在(标准)C ++中不允许,但在C(从C11开始)中你可以使用匿名结构:

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

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

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.x之后阅读v1.data_arr_format在技术上是未定义的行为。

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