是否有一种标准(或至少是安全的)方法来比较联盟在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
来搞定这项工作。
有人这样做吗?第一个(更简单)的实现安全吗? 不是否有任何理由这样做?
答案 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)
当然它不安全。
例如,您不能假设int
与char *
的大小相同。可能还有填充,内容中通常是随机的。