读取与活动的一个明确定义相同类型的非活动联盟成员吗?

时间:2015-06-14 07:24:49

标签: 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};
};

这样的东西似乎用于例如GLM提供类似GLSL的类型,例如vec4vec2等。

但是,虽然预期用途是为了使这成为可能

vec4 a(1,2,4,7);
a.x=7;
a.b=a.r;

,它似乎是一种未定义的行为,因为引用here

  

在联合中,最多一个数据成员可以随时处于活动状态,也就是说,任何时候最多一个数据成员的值都可以存储在一个联合中。

例如,不是更好吗?使用只需定义如下结构?

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;
    }
};

或者我是否正在解决一个不存在的问题?是否有一些特殊的声明允许访问相同类型的非活动联盟成员?

1 个答案:

答案 0 :(得分:-1)

我认为你所指的引用是针对联盟中的不同类型。

struct foo {
  union {
    float x,
    int y,
    double z,
  };
};

这些是不同的数据,方便地存储在同一个结构中,工会不应该是一个铸造机制。

GLM方法使用相同的数据,并使用union作为别名机制。

您的方法可能更好' C ++,但它更糟糕'工程'。矢量数学需要很快,在这种情况下越小越好。

您的实现使向量大3倍。 sizeof(glm::vec4); // 16 sizeof(your_vec4); // 48 - ouch your_vec4如果你处理大量的这些通常就是这种情况,那么缓存未使用struct { float x,y,z,w; }的次数就会增加3倍。

我认为你是正确的虽然glm使用工会作为别名有点多,但我不确定它是否未定义,但这种类型的东西我是看到很多没有太多问题,glm被广泛使用。

我没有真正意识到需要在C ++中模仿glsl,// ScriptA String type; public void SetType(String _type){ type = _type; } 会更好(至少在我看来)。