2013-07-22 5 views
9

Minimal przykład kodu:C++ 11 „W inicjalizacji klasy” funkcja nie działa dla związków

struct B { 
    union U { 
    struct S {} s; 
    int i = 100; 
    } 
    u; 
}; 

Teraz jeśli zadeklarować B obj; wtedy obj.u.i przypisano wartość śmieci zamiast 100. Zobacz demo here. (Wartość śmieci różni się w zależności od flag optymalizacyjnych itp.).

Czy funkcja "W inicjalizacji klasy" powinna działać ze związkami.

  • Jeśli tak, to jaka jest prawidłowa składnia? Czy jest to błąd g ++?
  • Jeśli nie, to co robi int i = 100;?
+1

+1 Dobre pytanie. – Nawaz

+2

[klang] (http://coliru.stacked-crooked.com/view?id=6ab1a0f46b2229dfc46dfa6f4f5e3163-6e9f1f680880347f6708b805c806db62) wydaje się być zadowolony z twojego kodu. – Praetorian

+0

@Praetorian, Dzięki. Jednak nie wstawiłeś instrukcji wyjściowych. Więc tutaj jest poprawne [wyjście klang] (http://coliru.stacked-crooked.com/view?id=542928082d0e3f7d6edd525a7fcfac44-6e9f1f680880347f6708b805c806db62). – iammilind

Odpowiedz

3

To wygląda jak błąd GCC. Standard mówi (9.5p2):

At most one non-static data member of a union may have a brace-or-equal-initializer.

W przeciwnym razie zasady są takie same jak w przypadku zwykłej klasy.

EDIT: Dodatkowo 12.6.2p8:

In a non-delegating constructor, if a given non-static data member or base class is not designated by a mem-initializer-id (including the case where there is no mem-initializer-list because the constructor has no ctor-initializer) and the entity is not a virtual base class of an abstract class (10.4), then

  • if the entity is a non-static data member that has a brace-or-equal-initializer, the entity is initialized as specified in 8.5;
  • otherwise, if the entity is a variant member (9.5), no initialization is performed;
  • otherwise, the entity is default-initialized (8.5).

Przypuszczalnie domyślnie zdefiniowany konstruktor domyślny zlicza tutaj. Członek i spełnia kryteria w pierwszym punkcie wypunktowania, więc został zainicjowany tak, jakby był zwykłym członkiem klasy. Element s pasuje do drugiego punktu wypunktowania, więc pozostaje niezainicjowany.

+0

Jakieś rozwiązanie z obecnym kodem? – iammilind

+0

Nie kompiluje się na VS 2010 i 2012, nawet w pierwszej wersji, z błędem: tylko statyczne integralne elementy danych mogą zostać zainicjowane w ramach klasy. Albo oba kompilatory mają błąd lub jest coś więcej ... – neagoegab

+0

@neagoegab Żadna z tych wersji VS nie obsługuje in-class initialization of data members. [klang] (http://coliru.stacked-crooked.com/view?id=6ab1a0f46b2229dfc46dfa6f4f5e3163-6e9f1f680880347f6708b805c806db62) kompiluje kod bez błędów. – Praetorian

2

Myślę, że tak jest, ponieważ związek jednoczy więcej niż jeden element. Poniżej znajduje się opis składni:

struct B { 
    union U { 
    int i; 
    } 
    u {100}; 
}; 

int main() { 
    B obj; 
    std::cout << "obj.u.i = " << obj.u.i << "\n"; 
} 
+1

Proszę przestać zgadywać. Opublikuj odpowiedź, którą znasz * i możesz ją wspierać. – Nawaz

+0

@Nawaz, wierzę, że poparłem moją odpowiedź. Alternatywą jest znalezienie go w standardzie, ale jesteś szybszy ode mnie: D, ale zaktualizuję odpowiedź. – neagoegab

+0

To rozwiązanie nie działa z moim rzeczywistym problemem, po prostu dodaj 'struct S {} s;' wewnątrz 'union U', a program daje [błąd kompilatora] (http://ideone.com/5tS7q9). Odpowiednio zaktualizowałem pytanie. – iammilind