Czy w C ++ operator?: Jest szybszy niż instrukcje if () ... else? Czy są między nimi różnice w skompilowanym kodzie?
if
zezwala na instrukcje.
Czy w C ++ operator?: Jest szybszy niż instrukcje if () ... else? Czy są między nimi różnice w skompilowanym kodzie?
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.
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
.
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ąc if
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”.
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 generowanie cmove
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”)
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 ...
x ? y : x = value
przypisuje wartość do Y , jeśli x nie jest równa 0 (fałsz).
Niezależnie od skompilowanego kodu, są semantycznie różne. <cond>?<true expr>:<false expr>
jest wyrażeniem i if..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 ++, zamiast if..else..
instrukcji.
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ę.
W CA dostępny jest operator trójskładnikowy „?:” Do konstruowania wyrażeń warunkowych formularza
exp1 ? exp2:exp3
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. *
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
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.
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 co b
. 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ąć.
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
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ć.