Opcja g ++ -Wall obejmuje -Wreorder. Działanie tej opcji opisano poniżej. Nie jest dla mnie oczywiste, dlaczego kogoś to obchodzi (szczególnie na tyle, aby włączyć to domyślnie w -Wall).
-Wreorder (tylko C ++) Ostrzegaj, gdy kolejność inicjatorów składowych podana w kodzie nie pasują do kolejności, w jakiej muszą być wykonywane. Na przykład: struct A { int i; int j; A (): j (0), i (1) {} }; Kompilator zmieni kolejność inicjatorów składowych dla i i j do dopasować kolejność deklaracji członków, wysyłając ostrzeżenie efekt. To ostrzeżenie jest włączane przez -Wall.
c++
g++
compiler-warnings
Peeter Joot
źródło
źródło
-Werror=reorder
Odpowiedzi:
Rozważać:
Teraz
i
jest inicjalizowany na nieznaną wartość, a nie na zero.Alternatywnie inicjalizacja
i
może mieć pewne skutki uboczne, dla których ważna jest kolejność. Na przykładźródło
i
jest zainicjowany1
). Tutaji
jest zainicjowanyj
, co w rzeczywistości pokazuje problem.Problem polega na tym, że ktoś może zobaczyć listę inicjatorów składowych w konstruktorze i pomyśleć, że są one wykonywane w tej kolejności (najpierw j, potem i). Nie są, są wykonywane w kolejności, w jakiej elementy członkowskie są zdefiniowane w klasie.
Przypuśćmy, że napisałeś
A(): j(0), i(j) {}
. Ktoś mógłby to przeczytać i pomyśleć, że otrzymuję wartość 0. Tak nie jest, ponieważ zainicjowałeś go za pomocą j, który zawiera śmieci, ponieważ sam nie został zainicjalizowany.Ostrzeżenie przypomina o konieczności pisania
A(): i(j), j(0) {}
, co, miejmy nadzieję, wygląda o wiele bardziej podejrzanie.źródło
Inne odpowiedzi dostarczyły dobrych przykładów, które uzasadniają opcję ostrzeżenia. Pomyślałem, że przedstawię kontekst historyczny. Twórca C ++, Bjarne Stroustrup, wyjaśnia w swojej książce Język programowania C ++ (wydanie trzecie, strona 259):
źródło
Może to Cię ugryźć, jeśli inicjatory mają skutki uboczne. Rozważać:
Powyższe wypisze „bar”, a następnie „foo”, chociaż intuicyjnie można by założyć, że kolejność jest taka, jak zapisano na liście inicjalizacyjnej.
Alternatywnie, jeśli
x
iy
są typu zdefiniowanego przez użytkownika z konstruktorem, ten konstruktor może również mieć skutki uboczne z tym samym nieoczywistym wynikiem.Może się również objawiać, gdy inicjator dla jednego elementu członkowskiego odwołuje się do innego elementu członkowskiego.
źródło
Ostrzeżenie istnieje, ponieważ jeśli po prostu przeczytasz konstruktora, wygląda na to, że
j
został zainicjowany wcześnieji
. Staje się to problemem, jeśli jeden jest używany do inicjalizacji drugiego, jak wKiedy tylko spojrzysz na konstruktora, wygląda to bezpiecznie. Ale w rzeczywistości
j
nie został jeszcze zainicjowany w momencie, w którym jest używany do inicjalizacjii
, więc kod nie będzie działał zgodnie z oczekiwaniami. Stąd ostrzeżenie.źródło