2017-11-07 76 views
6

Co sprawia, że ​​członek związku jest aktywny?Co sprawia, że ​​członek związku jest aktywny?

Przeczytałem rozdział 9.5 standardu C++ 14 (ten o związkach), ale nie znalazłem jednoznacznej odpowiedzi na pytanie, co sprawia, że ​​członek związku jest aktywny.

Jest uwaga:

Ogólnie, trzeba używać wyraźnych połączeń spalające i rozmieszczenie nowych operatorów zmienić aktywnym członkiem Unii.

Tak na przykład,

union U { 
    int i; 
    short s; 
} u; 

new(&u.i) int(42); 

porządku, pośrednictwa nowe zmiany aktywnym członkiem, to jasne. Ale zwykle nie używamy nowego miejsca podczas pracy z typami z trywialnymi konstruktorami.

Czy operator= zmienia aktywny element bez UB?

u.i = 42; 

Tutaj, operator= zadzwonił na niezbudowany obiekt. Czy jest dobrze zdefiniowany?

Co z tym?

struct A { 
    int i0; 
    int i1; 
}; 
union U { 
    A a; 
    short s; 
} u; 

Co sprawia a być aktywnym członkiem u? Czy wystarczająca jest wystarczająca ilość pamięci?

u.a.i0 = 42; 
u.a.i1 = 99; 

Co jeśli piszę:

u.a.i0 = 42;  // supposedly this doesn't change the active member to a, as i1 isn't set 
int x = u.a.i0; // is it fine to read from a.i0? a is not an active member supposedly 

Po u.a.i0 = 42;, aktywny członek nie jest zmieniany na a (chyba), więc jest to do zrobienia int x = u.a.i0; UB?

Czy C++ 17 poprawia opis aktywnych członków?

+0

„Tutaj operatora' = 'nazwie na zasadzie niezabudowana obiekt "jesteś pewien? To POD, więc wydaje się dobrze. – BartoszKP

+1

Definicja laika jest taka, że ​​jest to element, na który ostatnio napisano. Ale nie mogę znaleźć żadnego uzasadnienia tego w standardzie. – SergeyA

+0

@BartoszKP: cóż, to DynamicType to na pewno (?) Nie 'int', więc ... nie wiem :) – geza

Odpowiedz

5

C++ 17, akapit dodano jawnie opisano przypadki jak u.i = 42:

[class.union]/5 gdy lewy argument operatora przypisania obejmuje ekspresję dostępu element (8.2.5), który wyznacza członka związku, może rozpocząć życie tego członka związku, jak opisano poniżej. Dla ekspresji E, określa zestaw S(E) z Podwyrażenia E następująco:

(5,1) - Jeżeli E ma postać A.B, S(E) zawiera elementy S(A), a także zawiera A.B IF B imiona człon złączkową nieklasy, typu tablicowego lub typu klasy z trywialnym domyślnym konstruktorem, który nie jest usuwany, lub tablicą takich typów.

(5.2) - Jeśli E ma postać A[B] i jest interpretowany jako wbudowany operator indeksowania tablicy, S(E) jest S(A), jeśli A jest typu tablicowego, S(B), jeśli B jest typu tablicowego, a puste w przeciwnym razie.

(5.3) - W przeciwnym razie S(E) jest pusty.

w wyrażeniu przypisania postaci E1 = E2 używającą wbudowanego operatora przypisania (8,18) lub najdrobniejszy operatora przypisania (15,8), dla każdego elementu X z S(E1) jeżeli modyfikacja X musiałby nieokreśloną reakcję na 6,8 obiekt typu X jest domyślnie tworzony w wyznaczonej pamięci; nie przeprowadza się inicjalizacji, a początek jej okresu jest sekwencjonowany po obliczeniu wartości lewego i prawego argumentu operacji i przed przypisaniem. [Uwaga: To kończy czas życia poprzednio aktywnego członka unii, jeśli istnieje (6.8). końcem uwaga]

(Obserwowani przez dość długi przykład, że jestem zbyt leniwy, aby prawidłowo sformatować, ale które można zobaczyć here.)