Поиск…


замечания

Союзы - очень полезные инструменты, но приходят с несколькими важными оговорками:

  • Неопределенное поведение по стандарту C ++ для доступа к элементу объединения, который не был последним измененным членом. Хотя многие компиляторы C ++ разрешают этот доступ определенными способами, это расширения и не могут быть гарантированы в разных компиляторах.

    std::variant (поскольку C ++ 17) подобен объединению, только он сообщает вам, что он в настоящее время содержит (часть его видимого состояния - это тип значения, которое он имеет в данный момент: он обеспечивает доступ к значениям, доступным только к этому типу).

  • Реализации не обязательно выравнивают членов разных размеров по одному и тому же адресу.

Основные возможности соединения

Союзы - это специализированная структура, внутри которой все члены занимают перекрывающуюся память.

union U {
    int a;
    short b;
    float c;
};
U u;

//Address of a and b will be equal
(void*)&u.a == (void*)&u.b;
(void*)&u.a == (void*)&u.c;

//Assigning to any union member changes the shared memory of all members
u.c = 4.f;
u.a = 5;
u.c != 4.f;

Типичное использование

Союзы полезны для минимизации использования памяти для исключительных данных, например, при реализации смешанных типов данных.

struct AnyType {
    enum {
        IS_INT,
        IS_FLOAT
    } type;
    
    union Data {
        int as_int;
        float as_float;
    } value;

    AnyType(int i) : type(IS_INT) { value.as_int = i; }
    AnyType(float f) : type(IS_FLOAT) { value.as_float = f; }

    int get_int() const {
        if(type == IS_INT)
            return value.as_int;
        else
            return (int)value.as_float;
    }
    
    float get_float() const {
        if(type == IS_FLOAT)
            return value.as_float;
        else
            return (float)value.as_int;
    }
};

Неопределенное поведение

union U {
    int a;
    short b;
    float c;
};
U u;

u.a = 10;
if (u.b == 10) {
   // this is undefined behavior since 'a' was the last member to be
   // written to. A lot of compilers will allow this and might issue a
   // warning, but the result will be "as expected"; this is a compiler
   // extension and cannot be guaranteed across compilers (i.e. this is
   // not compliant/portable code).
}


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow