为什么工会静态成员不存储为工会?

Why union static members not stored as a union?

本文关键字:存储 静态成员 为什么      更新时间:2023-10-16

In C++union可以包含静态成员,这些静态成员与类一样,属于一个类,因此对所有对象都是通用的。

union U
{
long l;
int i;
static long sl;
static int si;
};
int U::si;
long U::sl;

期望所有联合静态成员存储在同一地址类似于非静态成员存储是合乎逻辑的。但事实并非如此。一个简单的示例显示静态成员存储在不同的地址下,并且可以包含独立的值。

int main()
{
U u;
u.si = 10;
u.sl = 50;
std::cout << "Non-static members adresses: " << &u.i << " " << &u.l << std::endl;
std::cout << "Static members adresses: " << &u.si << " " << &u.sl << std::endl;
std::cout << "Static members values: " << u.si << " " << u.sl << std::endl;
return 0;
}

输出:

Non-static members adresses: 006FF8EC 006FF8EC
Static members adresses: 00AEB144 00AEB140
Static members values: 10 50

我不明白为什么独立的价值存储留在工会中。我认为这是误导,毫无意义。尽管如此,在我看来,这是有原因的。union静态成员的目的是什么?

你可以从两个角度来看待这个问题。

C++视角:

工会首先是一个阶级。它有一个不同于类的目的,但它是由类是什么来告知的。

联合是一个类,其子对象在任一类型中只有一个处于活动状态。为此,它改变了工会的成员子对象的工作方式。这也是联合不能有基类子对象的部分原因。

静态数据成员不是成员子对象,因此它们在联合中的处置应该与它们在非联合类中的处置没有什么不同。

此外,C++ 中类型的静态成员实际上只是函数和对象名称的作用域机制。它们仍然是有效的全局的,但它们可以是私有的和隐藏的,并且它们必须以它们的类型名称为前缀才能使用它们。

联合的静态数据成员的行为与类的静态数据成员没有任何不同,这实际上没有任何意义。

C++必须与 C 兼容的视角:

联合存在于 C 中,所以C++也必须拥有它们。但是联合很难在C++对象模型中定义,使用起来很痛苦,还有很多其他事情。因此,你可以将工会视为C++需要拥有但宁愿不处理的事情。那你怎么处理他们呢?

在处理 C 工会的工作方式时,你让工会像 C 一样工作。在 C 中没有静态成员这样的东西,所以没有 C 代码期望静态联合成员被组合在一起。因此。。。不要将它们组合在一起。如果用户确实需要一个静态成员,该成员是一组类型的联合,则他们可以轻松地创建联合并创建该类型的单个静态成员。

因此,用户不会因为使静态成员与众不同而失去任何表达能力。

联合是一次最多保存一个数据成员的类 [basic.compound]p1.6 [class]p7 [class.union],并且对于其静态数据成员没有特殊规则,其余类类型(即classstruct)。

因此,静态数据成员的行为与所有类中的行为相同。

如果要拥有一个由多种类型联合的静态数据成员,则可以执行以下操作:

union U {
long l;
int i;
union {
long l;
int i;
} static s;
};
decltype(U::s) U::s;
// They are the same indeed
static_assert(&U().s.l == &U().s.l);

您需要通过s引用元素,例如 不过,s.l而不是sl