Rus*_*lan 7 c++ undefined-behavior unions
考虑以下结构:
struct vec4
{
union{float x; float r; float s};
union{float y; float g; float t};
union{float z; float b; float p};
union{float w; float a; float q};
};
Run Code Online (Sandbox Code Playgroud)
像这样的东西似乎比如可以应用于GLM提供GLSL般的类型,如vec4,vec2等.
但是,尽管预期的用途是使这成为可能
vec4 a(1,2,4,7);
a.x=7;
a.b=a.r;
Run Code Online (Sandbox Code Playgroud)
,它似乎是一个未定义的行为,因为,如这里引用的,
在联合中,最多一个数据成员可以在任何时间处于活动状态,也就是说,最多一个数据成员的值可以随时存储在并集中.
例如,使用仅仅定义类似下面的结构不是更好吗?
struct vec4
{
float x,y,z,w;
float &r,&g,&b,&a;
float &s,&t,&p,&q;
vec4(float X,float Y,float Z,float W)
:x(X),y(Y),z(Z),w(W),
r(x),g(y),b(z),a(w),
s(x),t(y),p(z),q(w)
{}
vec4()
:r(x),g(y),b(z),a(w),
s(x),t(y),p(z),q(w)
{}
vec4(const vec4& rhs)
:x(rhs.x),y(rhs.y),z(rhs.z),w(rhs.w),
r(x),g(y),b(z),a(w),
s(x),t(y),p(z),q(w)
{}
vec4& operator=(const vec4& rhs)
{
x=rhs.x;
y=rhs.y;
z=rhs.z;
w=rhs.w;
return *this;
}
};
Run Code Online (Sandbox Code Playgroud)
还是我在解决一个不存在的问题?是否可能有一些特殊声明允许访问相同类型的非活动联盟成员?
小智 -1
我认为您所指的引用是针对在联合中使用不同类型的。
struct foo {
union {
float x,
int y,
double z,
};
};
Run Code Online (Sandbox Code Playgroud)
这些是不同的数据,可以方便地存储到相同的结构中,联合不应该是一种转换机制。
GLM 方法使用相同的数据并使用联合作为别名机制。
你的方法可能是“更好的”C++,但它是更糟糕的“工程”。矢量数学需要很快,在这种情况下越小越好。
您的实现使向量变大了 3 倍。sizeof(glm::vec4); // 16而sizeof(your_vec4); // 48 - ouch如果您处理大量此类数据(通常是这种情况),则缓存未命中数会增加 3 倍your_vec4。
我认为你是对的,虽然 glm 使用联合作为别名有点多,虽然我不确定它是否未定义,但这种类型的东西我见过很多,没有太多问题,而且 glm 被广泛使用。
我真的不认为有必要在 C++ 中模拟 glsl,而且struct { float x,y,z,w; }会更好(至少在我看来)。