在类中使用联合
Posted
技术标签:
【中文标题】在类中使用联合【英文标题】:Usage of union inside a class 【发布时间】:2011-03-27 23:19:51 【问题描述】:我看到一些代码如下:
class A
private:
union
B *rep;
A *next;
; // no variables of this anonymous defined!
void func()
A *p = new A;
p->next = NULL; // why p has a member variable of 'next'?
;
我已经用VS2010编译了上面的代码,没有任何错误。 问题来了,
为什么 p 有成员变量 'next'?
union
B *rep;
A *next;
;
据我所知,这是一个匿名联合,甚至没有定义变量。我们怎样才能像那样访问这个联合内部的成员变量?
【问题讨论】:
【参考方案1】:因为这几乎就是匿名联合所做的,所以它在封闭的命名空间中定义了零个或多个变量(在类声明中使它们成为字段名称),这些变量占用重叠的内存。因此在使用中它就像你声明的一样
class A
private:
B *rep;
A *next;
void func()
A *p = new A;
p->next = NULL;
;
...除了 rep 和 next 占用重叠空间(或者假设两个指针将具有相同的大小,相同的空间),因此命名联合带来的所有危险和好处。
【讨论】:
'因为这几乎就是匿名工会所做的'——这是一个很好的观点。如果我在联合定义的末尾提供了一个变量,那么代码将不再正确——谢谢【参考方案2】:这是控制此行为的标准引用:[class.union]
部分(措辞来自 C++0x 草案 n3242)
形式的联合
union
member-specification;
被称为匿名联合;它定义了一个未命名类型的未命名对象。匿名联合的成员规范应该只定义非静态数据成员。 [ 注意:嵌套类型和函数不能在匿名联合中声明。 — 尾注] 匿名联合成员的名称应与声明匿名联合的范围内的任何其他实体的名称不同。出于名称查找的目的,在匿名联合定义之后,匿名联合的成员被认为是在声明匿名联合的范围内定义的。
【讨论】:
@q0987:我认为Jon 赢得了复选标记。我什么也没做,只是引用标准作为参考,以证明他更具可读性的答案是正确的。我会使用评论,但我很久以前就知道标准中的引用通常不适合评论,它们的格式也不正确。【参考方案3】:我不确定我是否理解您的问题。
A 有成员 p,因为您在 A 中与 rep 一起在匿名联合中声明了它。
你确实声明了一个变量!只是'rep'和'next'共享同一个内存。
您可以像以前一样访问它。
匿名联合(就像结构一样)将它们的成员放在与上述命名空间相同的命名空间中。
它对例如:
很有用union W00t
struct
uint32_t a,b;
;
struct
uint64_t c;
;
【讨论】:
您的回答与我的问题无关。我问“为什么变量 p 可以访问变量下一个?” 嗯,我不明白,对不起^^。您确实声明了一个变量。只是它没有名称,因此使用上述命名空间?我不知道该说什么,真的。 next 确实是 A 的一部分。代表也是。两者都是成员......但是 rep 和 next 共享相同的 64 位内存。 ((并且 p 是 A*,因此是指向 A 实例的指针,因此具有 A 的所有成员。)) 将联合视为结构,其中每个成员都从相同的内存位置开始。 联合确实有很多围绕它们的用法的规则,这些规则似乎在每个标准版本中都发生了变化(并且在 C 和 C++ 之间有很大不同)。很难准确确定它们何时可用于记忆混叠。 T它们被明确定义为用作变体,即当您只读取最后一组的成员时;之后就变得模糊了【参考方案4】:我很惊讶有一个现代编译器仍然允许这种结构。它来自于 C 的早期,大约 1975 年。在那个时候,结构和联合成员实际上并没有绑定到特定的结构,而是作为属性包含从基地址和数据类型的偏移量。
最终结果是,正确使用结构或联合会产生正确的代码,并且表达式按预期进行评估。唯一的区别是滥用与类型无关的指针的结构成员不会被标记为错误。我认为不强制执行关联没有任何特别的原因——K&R 暗示未来的编译器希望会检查这种用途——可能只是为了在 16 位空间中节省符号表空间。
【讨论】:
最新的 gcc 喜欢它。而且 imo 如果您使用 union struct ... 之间不必有另一个范围/名称,这很有意义 当然编译器允许这种结构,它是标准的一部分(在 C++0x 中仍然是)。我会发布相关部分。 除了滥用以节省空间之外,它还有实际用途。在处理强加的物理布局时,在某些情况下,在 C 和 C++ 中可以做的很多“坏”事情是必要的,因此,如果节省空间是唯一的目的,上述情况将是不好的(尽管即使这样在一个小的情况下也是可以原谅的)只有几 KB 的设备),在某些情况下它绝对是至关重要的。 @BenVoigt 匿名联合在 C89 或 C99 中是不允许的。它们是在 C11 中添加的。 (当然,它们一直被允许在 C++ 中使用,Wally 可能正在考虑 C)以上是关于在类中使用联合的主要内容,如果未能解决你的问题,请参考以下文章