2017-02-06 22 views

Odpowiedz

3

Tak, ponieważ std::vector::resize i podobne metody wykonać inicjalizację wartości domyślnie co z kolei wartość inicjuje członków agregatów:

Od cppr:

Skutki inicjalizacji wartości to:
[...]
jeśli T jest typem klasy z domyślnym konstruktorem, który nie jest ani podany przez użytkownika, ani usunięty (to znaczy może być klasą z niejawnie zdefiniowanym lub defaulte d domyślny konstruktor), obiekt jest inicjalizowany od zera, a następnie jest inicjowany domyślnie, jeśli ma nietrywialny domyślny konstruktor;

i Zero Initialiation część robi to, czego potrzebujemy:

Jeśli T jest non-union typ klasy, wszystkie klasy bazowe i non-statyczne członkowie danych są zero-zainicjowany, a wszystko wyściółka jest inicjowany do zera bitów. Konstruktory, jeśli istnieją, są ignorowane.

I oczywiście, zero inicjalizacji naszego członka robi słusznie:

Jeśli T jest typem skalarne, wartość początkową obiektu jest integralną stała zerowa wyraźnie konwertowane do T.


Domyślny program przydzielający nie może używać innej alokacji. Można ich użyć, aby pozostawić takie wartości w jednostce zunifikowanej, patrz pełny artykuł na temat default-insert.

3

Czy powyższy program gwarantuje powrót do C++ 14? Czemu?

Tak. W [vector.capacity]

void resize(size_type sz);
13 Wpływ: if sz < size(), usuwa się ostatnie size() - sz elementy z sekwencji. W przeciwnym razie dołącza domyślne elementy do sekwencji.

gdzie z [container.requirements.general]

Element X jest domyślnych dodaje jeśli jest inicjowana na podstawie zmian ekspresji allocator_traits<A>::construct(m, p) gdzie p jest adres z niezainicjowana pamięć dla elementu przydzielonego w ramach X.

construct dla std::allocator<T> robi, z [default.allocator]:

template <class U, class... Args> 
void construct(U* p, Args&&... args); 

Effects: ::new((void *)p) U(std::forward<Args>(args)...)

Tak, to wartości inicjalizacji. Robimy new S(), a nie new S, więc członek x zostanie zinicjalizowany od zera.


Sposoby unikanie to zachowanie (w razie potrzeby) są albo:

  1. Zmiana podzielnik. Podaj swój własny typ alokatora, który ma dwa przeciążenia dla construct: jeden pusty (który wykonałby domyślną inicjalizację) i jeden pobierający Args&&....
  2. Zmień typ. Dodaj domyślny konstruktor do S, który nie inicjuje.
Powiązane problemy