max({"a", "b", "z", "x"}); returns "x"
natomiast zarównoC++ 's max() z listy inicjatora zwraca ciągi poza kolejnością
max<std::string>({"a", "b", "z", "x"});
i
max({'a', 'b', 'z', 'x'});
zwrot "z" tak, jak powinny. Czemu?
max({"a", "b", "z", "x"}); returns "x"
natomiast zarównoC++ 's max() z listy inicjatora zwraca ciągi poza kolejnością
max<std::string>({"a", "b", "z", "x"});
i
max({'a', 'b', 'z', 'x'});
zwrot "z" tak, jak powinny. Czemu?
"a"
, "b"
itd. Są literałami ciągów. Rozpadają się one na const char*
na liście inicjalizacyjnej. max
Po prostu
prawdopodobnie dostaje ten o najwyższym adresie, ale ponieważ używa go do porównania operator<
i nie są one częścią tej samej tablicy lub jednej przeszłości tej samej tablicy, wynik porównania jest nieokreślony (i wywołanie max
spowodowałoby nieokreślone zachowanie , ponieważ wymagane jest, aby typ był LessThanComparable
).
Pozostałe dwie inwokacje max
są dobrze zdefiniowane. char
s takie jak a
, b
itd. Są typami integralnymi o dobrze zdefiniowanym porównaniu mniejszym niż. I std::string
ma operator<
, który implementuje porównanie leksykograficzne.
max({"a", "b", "z", "x"});
próbuje porównać wskaźniki. Ma to niezdefiniowane zachowanie (ponieważ wyniki poszczególnych porównań są nieokreślone). To chciałeś porównać wskaźników, należy napisać:
std::max({"a", "b", "z", "x"}, std::less<const char*>());
Natomiast max({'a', 'b', 'z', 'x'});
porównuje wartości całkowite, a max<std::string>
porównuje ciągi.
Dlaczego zachowanie jest niezdefiniowane? –
@ P45Imminent: Operator '<' dla argumentów operacji jest zdefiniowany tylko dla wskaźników do podobiektów tego samego wspólnego obiektu. –
Dziękuję. Rewizja! –
Wynik porównania jest nieokreślony, a nie niezdefiniowany. –
@ T.C. Czy masz na to referencję? Domyślam się, że gdyby to było nieokreślone, to nadal wywoływałoby inwokację pod 'max' undefined, z powodu nie dostarczania ścisłej słabej kolejności. – juanchopanza
Ostatnie zdanie z [wyraż.rel]/p4. Ale dobry punkt o ścisłej słabej kolejności. –