工会的平等比较?

时间:2015-04-17 14:58:26

标签: c++ c unions discriminated-union

是否有一种标准(或至少是安全的)方法来比较联盟在C和/或C ++中的相等性?我希望在每个联合中最后分配的成员无论的情况下,按位比较都是有用的。例如,可以保留特定的位模式来表示“值未初始化”,并且能够在不需要指定“活动”成员的情况下检查联合是否未初始化是有用的。

C ++中的一个例子(虽然我认为这个概念使用非成员函数扩展到C):

union MyData
{
  public:
    // Assume I'm compiling this on a platform where the size of `int`
    // exceeds the size of `char*`, or that I'm using some combination
    // if `#ifdef`s or similar to ensure that my numeric type is sufficiently
    // large, or that I include an extra member that is known to be
    // exactly the size of the larger member, just for the sake of
    // comparison.
    int int_member;
    char* ptr_member;

    bool isInitialized() const
    {
      return (*this != INVALID_VAL);
    }

    bool operator==(MyData const& rhs)
    {
      return / * ??? */;
    }

  private:
    constexpr MyData INVALID_VAL { /* ??? */ };
}

// ... later, in client code...

MyData d;
bool initialized{d.isInitialized()};  // false
d.ptr_member = new char[32];
bool initialized{d.isInitialized()};  // true

这里,INVALID_VAL可能通过将int_member设置为最大负int值来定义,因为这是一个不均匀的值,因此它不会出现在单词边界上,因此极不可能永远被分配给char*成员(假设作业通常直接来自new)。

operator==的一种可能实现方式是:

return int_member == rhs.int_member;

即使不知道int_member是否是“活跃”成员,我希望这是安全的,因为我认为没有理由从char*int进行静态演员失败或有问题。这是对的吗?

如果此实现 不安全,则应该可以使用以下内容(当然,在C中使用C风格的强制转换):

return static_cast<void*>(*this) == static_cast<void*>(rhs);

...当然,如果MyData大于指针的大小,你必须开始使用sizeof来搞定这项工作。

有人这样做吗?第一个(更简单)的实现安全吗? 是否有任何理由这样做?

2 个答案:

答案 0 :(得分:3)

我认为更好的方法是将你的联合包装在一个类或结构中,并使用枚举字段存储,这是最后一个被访问的成员,例如。

class MyData {
    enum {
        unintialized, int_member, ptr_member
    } last_member = unintialized;

    union {
        int int_member;
        char* ptr_member;
    } union_fields;

public:
    bool isInitialized() const
    {
        return last_member != unintialized;
    }
};

如果您使用C ++ 11,则last_member的类初始化可以正常工作,否则只需在默认构造函数中初始化它。

为这两个字段创建访问器并相应地设置last_member,最好在访问器方法中添加检查,确保只有&#34;活动成员&#34;可以访问。

答案 1 :(得分:1)

当然它不安全。

例如,您不能假设intchar *的大小相同。可能还有填充,内容中通常是随机的。