简体   繁体   中英

Why union static members not stored as a union?

In C++ union can contain static members which, as in the case of classes, belong to a class and therefore are common to all objects.

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

int U::si;
long U::sl;

It would be logical to expect that all the union static members stored at the same address similar to non-static members storing. But it is not. A simple example shows that static members are stored under different addresses and can contain independent values.

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

Output:

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

I do not understand why independent values storing was left in unions. I think this is misleading and makes no sense. Nevertheless, it seems to me that there are reasons for this. What purpose of union static members?

You can look at this from two perspectives.

The C++ Perspective:

A union is, first and foremost, a class. It has a purpose distinct from a class, but it is informed by what a class is.

A union is a class for which only one of its subobjects is active at any one type. To this end, it changes how member subobjects of unions work. This is also part of why unions can't have base class subobjects.

Static data members are not member subobjects, so their disposition in a union should be no different from their disposition in a non-union class.

Furthermore, static members of types in C++ are really just a scoping mechanism for function and object names. They're still effectively global, but they can be private and hidden, and they have to be prefixed by their typename in order for you to use them.

It doesn't really make sense for static data members of a union to behave any differently from static data members of a class.

The C++-must-be-compatible-with-C Perspective:

Unions exist in C, so C++ has to have them too. But unions are difficult to define within the C++ object model, painful to work with, and a lot of other things. So you can think of unions as a thing that C++ needs to have but would rather not deal with. So how do you deal with them?

You make unions work like C when dealing with the way C unions work. There is no such thing in C as a static member, so there's no C code out there expecting static union members to be combined. Therefore... don't combine them. If the user genuinely needs a static member that is a union of some set of types, they can easily create a union and make a single static member of that type.

So the user doesn't lose any expressive power by making static members different.

Unions are classes that hold at most one data member at a time [basic.compound]p1.6 [class]p7 [class.union] , and there are no special rules for their static data members wrt the rest of class types (ie class and struct ).

Therefore, the static data members behave the same as in all classes.

If you want to have a static data member that is the union of several types, you could do something like:

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

You will need to refer to the elements via s , eg sl instead of sl , though.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM