Czy w C ++ operator?: Jest szybszy niż instrukcje if () ... else? Czy są między nimi różnice w skompilowanym kodzie?
c++
performance
conditional-operator
Xirdus
źródło
źródło
if
zezwala na instrukcje.Odpowiedzi:
Zależy od twojego kompilatora, ale w każdym nowoczesnym kompilatorze nie ma zasadniczo żadnej różnicy. To coś, o co nie powinieneś się martwić. Skoncentruj się na łatwości utrzymania swojego kodu.
źródło
To nie jest szybsze. Istnieje jedna różnica, kiedy można zainicjować stałą zmienną w zależności od jakiegoś wyrażenia:
const int x = (a<b) ? b : a;
Nie możesz zrobić tego samego z
if-else
.źródło
const
zmiennej.max
?const int x = max(a,b);
działa dobrze.max ? const int x = max(a,b);
i pomyślałem, że! Co to do cholery jest! potem przeczytałem go ponownie i zauważyłem, że znak zapytania nie był stały! biorąc pod uwagę temat, myślę, że uzasadnione było myślenie? był częścią dowództwa! :)const int x = [&] -> int { if (a < b) return b; else return a; }
.Widziałem, jak GCC zamieniało operator
cmov
warunkowy w instrukcje (ruch warunkowy), jednocześnie zamieniającif
instrukcje w gałęzie, co w naszym przypadku oznaczało, że kod był szybszy, gdy używał operatora warunkowego. Ale to było kilka lat temu i najprawdopodobniej dzisiaj, oba skompilowałyby się do tego samego kodu.Nie ma gwarancji, że skompilują się do tego samego kodu. Jeśli potrzebujesz wydajności, jak zawsze, zmierz . A kiedy już zmierzysz i odkryjesz, że 1. twój kod jest zbyt wolny, i 2. to ten konkretny fragment kodu jest winowajcą, wtedy przestudiuj kod asemblera wygenerowany przez kompilator i sprawdź sam, co się dzieje.
Nie ufaj złotym regułom, takim jak „kompilator zawsze wygeneruje wydajniejszy kod, jeśli użyję operatora warunkowego”.
źródło
Only one of the second and third expressions is evaluated. Every value computation and side effect associated with the first expression is sequenced before every value computation and side effect associated with the second or third expression.
co najwyraźniej uniemożliwia kompilatorowi generowaniecmove
instrukcji.Są takie same, jednak operator trójskładnikowy może być używany w miejscach, w których trudno jest użyć if / else:
printf("Total: %d item%s", cnt, cnt != 1 ? "s" : "");
Wykonanie tej instrukcji z if / else wygenerowałoby zupełnie inny skompilowany kod.
Aktualizacja po 8 latach ...
Właściwie myślę, że tak byłoby lepiej:
printf(cnt == 1 ? "Total: %d item" : "Total: %d items", cnt);
(właściwie jestem pewien, że „% d” w pierwszym ciągu znaków można zamienić na „jeden”)
źródło
printf("Total: %d item%s", cnt, "s" + (cnt==1));
lpStrFilter
składniku struktur OPENFILENAME )%s
Drukuje do, ale bez\0
ciągu źródłowego.printf("Total: %d item%s", cnt, "s" + (cnt==1));
działa?(cnt==1)
jest prawdą lub fałszem, co jest konwertowane na 0 lub 1. „s” jest wskaźnikiem do łańcucha zakończonego znakiem nul. Dodanie jednego pomija jeden znak (znaki). Więc to wypisuje „s” lub „”.Żeby być trochę leworęcznym ...
przypisuje wartość do Y , jeśli x nie jest równa 0 (fałsz).
źródło
Niezależnie od skompilowanego kodu, są semantycznie różne.
<cond>?<true expr>:<false expr>
jest wyrażeniem iif..else..
jest stwierdzeniem.Chociaż składnia wyrażeń warunkowych wydaje się niezręczna, to dobrze. Jesteś zmuszony podać a,
<false expr>
a dwa wyrażenia są sprawdzane pod względem typu.Odpowiednik
if..else..
w języku funkcjonalnym opartym na wyrażeniach, takim jak Lisp, Haskell jest? :
w C ++, zamiastif..else..
instrukcji.źródło
Nie jesteś zmuszony umieścić tego wszystkiego w jednej linii: -
x = y==1 ? 2 :// else 3;
Jest to o wiele jaśniejsze niż if / else, ponieważ od razu widać, że obie gałęzie prowadzą do przypisania x.
źródło
Spodziewałbym się, że na większości kompilatorów i platform docelowych będą przypadki, w których „if” jest szybsze i przypadki, w których?: Jest szybsze. Będą również przypadki, w których jedna forma jest mniej lub bardziej zwarta niż druga. Które przypadki faworyzują jedną lub drugą formę, będą się różnić w zależności od kompilatorów i platform. Jeśli piszesz kod krytyczny dla wydajności w osadzonym mikro, spójrz, co kompilator generuje w każdym przypadku i zobacz, co jest lepsze. Na komputerze typu „mainstream”, ze względu na problemy z buforowaniem, jedynym sposobem sprawdzenia, która jest lepsza, jest porównanie obu formularzy w sposób przypominający rzeczywistą aplikację.
źródło
W CA dostępny jest operator trójskładnikowy „?:” Do konstruowania wyrażeń warunkowych formularza
gdzie exp1, exp2 i exp3 są wyrażeniami
na przykład
a=20; b=25; x=(a>b)?a:b; in the above example x value will be assigned to b;
Można to zapisać za pomocą instrukcji if..else w następujący sposób
if (a>b) x=a; else x=b;
** Dlatego nie ma różnicy między tymi dwoma. To dla programisty, aby mógł łatwo pisać, ale dla kompilatora oba są takie same. *
źródło
Podczas cofania jakiegoś kodu (którego nie pamiętam, kilka lat temu) zauważyłem pojedynczą różnicę między kodem maszynowym:? a jeśli jeszcze.
Don't remember much but it is clear that implementation of both is different.
Ale radzę Ci nie wybierać jednego z nich ze względu na jego wydajność, wybierz ze względu na czytelność kodu lub wygodę. Miłego kodowania
źródło
Operator trójargumentowy zawsze zwraca wartość. Więc w sytuacji, gdy chcesz uzyskać jakąś wartość wyjściową z wyniku i są tylko 2 warunki, zawsze lepiej użyć operatora trójskładnikowego. Użyj if-else, jeśli którykolwiek z powyższych warunków nie jest spełniony.
źródło
Myślę, że są sytuacje, w których wbudowane if może dać „szybszy” kod ze względu na zakres, w jakim działa. Tworzenie i niszczenie obiektów może być kosztowne, więc rozważ następujący scenariusz:
class A{ public: A() : value(0) { cout << "Default ctor" << endl; } A(int myInt) : value(myInt) { cout << "Overloaded ctor" << endl; } A& operator=(const A& other){ cout << "= operator" << endl; value = other.value; } ~A(){ cout << "destroyed" << std::endl; } int value; }; int main() { { A a; if(true){ a = A(5); }else{ a = A(10); } } cout << "Next test" << endl; { A b = true? A(5) : A(10); } return 0; }
Z tym kodem wynik będzie:
Default ctor Overloaded ctor = operator destroyed destroyed Next test Overloaded ctor destroyed
Dlatego wstawiając if, oszczędzamy szereg operacji potrzebnych do utrzymania
a
tego samego zakresu cob
. Chociaż jest wysoce prawdopodobne, że szybkość oceny stanu jest dość równa w obu scenariuszach, zmiana zakresu zmusza Cię do wzięcia pod uwagę innych czynników, których inline pozwala uniknąć.źródło
A a(true ? 5 : 10);
Teraz nie mogę ci w tym pomóc, być może będę mógł pomóc w drugorzędnym pytaniu poniżej, czy chcę go użyć? Jeśli chcesz tylko poznać prędkość, zignoruj mój komentarz.
Mogę tylko powiedzieć, że proszę być bardzo sprytnym, kiedy używać trójskładnika? : operator. Może to być zarówno błogosławieństwo, jak i przekleństwo dla czytelności.
Zadaj sobie pytanie, czy łatwiej ci to przeczytać przed użyciem
int x = x == 1 ? x = 1 : x = 1; if (x == 1) { x = 1 } else { x = 2 } if (x == 1) x = 1 else x = 1
Tak, wykonanie kodu w 100% fałszywego wygląda głupio. Ale ta mała sztuczka pomogła mi przeanalizować moją czytelność kodu. To czytelność operatora, na który patrzysz w tym przykładzie, a nie treść.
WYGLĄDA czysto, podobnie jak przeciętna deska sedesowa i klamka
Z mojego doświadczenia, które jest ograniczone, widziałem bardzo niewielu ludzi, którzy faktycznie byli w stanie szybko ekstradować informacje wymagane od operatora trójskładnikowego, unikając ich, chyba że w 100% są pewni, że jest lepiej. Myślę, że to ból do naprawienia, gdy jest podłączony do sieci
źródło
int x = x == 1 ? 1 : 2
lub być możeint x = (x == 1) ? 1 : 2
x = x = 1;
wszędzie, a potem narzekasz, że zadanie jest zbyt skomplikowane i powinno się go unikać.Nie, są konwertowane na dokładnie ten sam kod wykonywalny.
źródło