调用非活动联盟成员的成员功能

问题描述 投票:1回答:1

是否调用 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;
}

根据标准。xdata 有相同的地址,所以应该可以安全地投下 thisvec*. 还有: field0vec 是布局兼容的,所以应该可以安全地检查 data 通过 x.data 或反之亦然。

然而,我们不仅要检查 x.data的非静态成员函数,我们调用 x 在它的生命之外(还是我们?我找不到一个理由 x 终身应该开始了),所以形式上是UB。这样说对吗?

我想实现的是定义好的常见方法的版本,如命名数组领域的 union a { int data[3]; int x, y, z};

更新。

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

  2. 我将需要使用 a 值的函数,以 int*因此,在另一个方向上--声明字段并重载 operator[] - 不是一个选项。

c++ union undefined-behavior
1个回答
4
投票

你的代码有未定义的行为。 初始公共序列规则在这里帮不了你,因为你不是在访问一个公共成员,而是在访问整个对象,以便调用成员函数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;
        }
    }
};

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

© www.soinside.com 2019 - 2024. All rights reserved.