Почему статические члены union не хранятся как union? - PullRequest
1 голос
/ 05 апреля 2019

В 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 статических членов?

Ответы [ 2 ]

7 голосов
/ 05 апреля 2019

Вы можете взглянуть на это с двух точек зрения.

Перспектива C ++:

Объединение - это, в первую очередь, класс.У него есть цель, отличная от класса, но она определяется тем, что есть класс.

Объединение - это класс, для которого только один из его подобъектов активен в любом одном типе.С этой целью он меняет работу дочерних подобъектов союзов.Это также является частью того, почему профсоюзы не могут иметь субобъектов base class .

Статические члены-данные не являются подобъектами-членами, поэтому их расположение в объединении не должно отличаться от их расположения вне объединяющий класс.

Более того, статические члены типов в C ++ на самом деле являются просто механизмом видимости для имен функций и объектов.Они по-прежнему эффективно глобальны, но они могут быть частными и скрытыми, и для их использования они должны иметь префикс по их типу.

Это не имеет смысла для членов статических данныхобъединение, которое будет вести себя иначе, чем члены статических данных класса.

Перспектива C ++ - должна быть совместима с-C:

В C существуют объединения, поэтому C ++ должен иметьих тоже.Но союзы сложно определить в объектной модели C ++, с ними трудно работать и многое другое.Таким образом, вы можете думать о профсоюзах, как о том, что нужно С ++, но не стоит иметь с ним дело.Итак, как вы справляетесь с ними?

Вы заставляете профсоюзы работать как С, когда имеете дело с тем, как работают профсоюзы С.В C нет такого понятия, как статический член, поэтому нет кода на C, который ожидает объединения статических членов объединения.Поэтому ... не объединяйте их.Если пользователю действительно нужен статический член, представляющий собой объединение некоторого набора типов, он может легко создать объединение и создать один статический член этого типа.

Таким образом, пользователь не теряет никакой выразительной силыделая различные статические элементы.

2 голосов
/ 05 апреля 2019

Союзы - это классы, в которых одновременно хранится не более одного элемента данных [basic.compound] p1.6 [class] p7 [class.union] и не существует специальных правил для их статических членов-данных относительно остальных типов классов (т. е. class и struct).

Следовательно, члены статических данных ведут себя так же, как и во всех классах.

Если вы хотите иметь статический элемент данных, который является объединением нескольких типов, вы можете сделать что-то вроде:

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, хотя.

...