调用非活动联合成员的成员函数

mih*_*ild 3 c++ union undefined-behavior

调用foo以下代码会导致UB吗?

using vec = std::array<int, 1>;
struct field0 {
    vec data;
    operator int() {
        return data[0];
    }
};

union a {
    struct {
        vec data;
    } data;
    field0 x;
};

void foo() {
    a bar;
    std::cin >> bar.data.data[0];
    std::cout << bar.x;
}
Run Code Online (Sandbox Code Playgroud)

根据标准,x并且data具有相同的地址,因此强制转换thisvec*. 此外,field0并且与vec布局兼容,因此data通过x.data或反之亦然检查应该是安全的。

然而,我们不只是检查x.data,我们x在它的生命周期之外调用非静态成员函数(或者我们?我找不到x生命周期应该开始的原因),所以正式它是UB。这是正确的吗?

我想要实现的是名称数组字段的通用方法的明确定义版本,例如 union a { int data[3]; int x, y, z};

更新:

  1. 抱歉,在删除不必要的细节时,数组字段和“getter”之间的布局兼容性丢失了。现在恢复了。

  2. 我将需要使用a值来运行它int*,所以在其他方向 - 声明字段和重载operator[]- 不是一个选项。

Nat*_*ica 5

您的代码具有未定义的行为。初始公共序列规则在这里对您没有帮助,因为您没有访问公共成员,而是访问整个对象以调用成员函数1

我想要实现的是名称数组字段的通用方法的明确定义版本,例如 union a { int data[3]; int x, y, z};

在 C++ 中这样做的方法是使用结构和运算符重载。不是拥有一个数组并试图将其映射到单个成员,而是拥有单个成员,然后假装您的类是一个数组。那看起来像

struct vec
{
    int x, y, z;
    int& operator[](size_t index)
    {
        switch(index)
        {
        case 0: return x;
        case 1: return y;
        case 2: return z;
        }
    }
};
Run Code Online (Sandbox Code Playgroud)

1:调用成员函数就是将该对象传递给该函数,就好像它是该函数的第一个参数一样。