调用不活跃的union成员的成员函数
Call member function of non-active union member
在下面的代码中调用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;
}
根据标准,x
和 data
具有相同的地址,因此将 this
转换为 vec*
应该是安全的。此外,field0
和 vec
是布局兼容的,因此通过 x.data
检查 data
应该是安全的,反之亦然。
然而,我们不只是检查 x.data
,我们在 x
的生命周期之外调用非静态成员函数(或者是吗?我找不到 [=12] 的原因=] lifetime 应该已经开始了),所以正式它是 UB。正确吗?
我想要实现的是定义明确的命名数组字段常用方法的版本,例如 union a { int data[3]; int x, y, z};
更新:
抱歉,在删除不必要的细节时,数组字段和 "getter" 之间的布局兼容性丢失。现已恢复。
我将需要使用 a
值来实现需要 int*
的功能,因此朝另一个方向发展 - 声明字段并重载 operator[]
- 不是选项。
您的代码有未定义的行为。初始公共序列规则在这里不会帮助您,因为您不是访问公共成员,而是访问整个对象以调用成员函数1。
What I am trying to achieve is well-defined version of common approach to name array field like union a { int data[3]; int x, y, z};
在 C++ 中执行此操作的方法是使用结构和运算符重载。您不是拥有一个数组并尝试将其映射到各个成员,而是拥有各个成员,然后假装您的 class 是一个数组。看起来像
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:调用成员函数就是把那个对象传递给那个函数,就好像它是函数的第一个参数一样。
在下面的代码中调用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;
}
根据标准,x
和 data
具有相同的地址,因此将 this
转换为 vec*
应该是安全的。此外,field0
和 vec
是布局兼容的,因此通过 x.data
检查 data
应该是安全的,反之亦然。
然而,我们不只是检查 x.data
,我们在 x
的生命周期之外调用非静态成员函数(或者是吗?我找不到 [=12] 的原因=] lifetime 应该已经开始了),所以正式它是 UB。正确吗?
我想要实现的是定义明确的命名数组字段常用方法的版本,例如 union a { int data[3]; int x, y, z};
更新:
抱歉,在删除不必要的细节时,数组字段和 "getter" 之间的布局兼容性丢失。现已恢复。
我将需要使用
a
值来实现需要int*
的功能,因此朝另一个方向发展 - 声明字段并重载operator[]
- 不是选项。
您的代码有未定义的行为。初始公共序列规则在这里不会帮助您,因为您不是访问公共成员,而是访问整个对象以调用成员函数1。
What I am trying to achieve is well-defined version of common approach to name array field like
union a { int data[3]; int x, y, z};
在 C++ 中执行此操作的方法是使用结构和运算符重载。您不是拥有一个数组并尝试将其映射到各个成员,而是拥有各个成员,然后假装您的 class 是一个数组。看起来像
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:调用成员函数就是把那个对象传递给那个函数,就好像它是函数的第一个参数一样。