Używam przymiotnika „techniczny”, aby oznaczać zachowanie / dziwactwa językowe i skutki uboczne kompilatora, takie jak wydajność generowanego kodu.
W tym celu odpowiedź brzmi: nie (*). (*) To „Proszę skonsultować instrukcję obsługi procesora”. Jeśli pracujesz z jakimś zaawansowanym systemem RISC lub FPGA, może być konieczne sprawdzenie, jakie instrukcje są generowane i ile kosztują. Ale jeśli używasz prawie każdy konwencjonalny nowoczesną architekturę, to nie ma istotnej różnicy w poziomie kosztów pomiędzy procesorem lt
, eq
, ne
i gt
.
Jeśli używasz przypadek krawędź mogłaby się okazać, że !=
wymaga trzech operacji ( cmp
, not
, beq
) vs dwóch ( cmp
, blt xtr myo
). Ponownie RTM w tym przypadku.
W większości przypadków powodem jest defensywność / hartowanie, szczególnie podczas pracy ze wskaźnikami lub złożonymi pętlami. Rozważać
// highly contrived example
size_t count_chars(char c, const char* str, size_t len) {
size_t count = 0;
bool quoted = false;
const char* p = str;
while (p != str + len) {
if (*p == '"') {
quote = !quote;
++p;
}
if (*(p++) == c && !quoted)
++count;
}
return count;
}
Mniej wymyślnym przykładem może być użycie wartości zwracanych do wykonywania przyrostów, przyjmowanie danych od użytkownika:
#include <iostream>
int main() {
size_t len = 5, step;
for (size_t i = 0; i != len; ) {
std::cout << "i = " << i << ", step? " << std::flush;
std::cin >> step;
i += step; // here for emphasis, it could go in the for(;;)
}
}
Spróbuj tego i wprowadź wartości 1, 2, 10, 999.
Możesz temu zapobiec:
#include <iostream>
int main() {
size_t len = 5, step;
for (size_t i = 0; i != len; ) {
std::cout << "i = " << i << ", step? " << std::flush;
std::cin >> step;
if (step + i > len)
std::cout << "too much.\n";
else
i += step;
}
}
Ale prawdopodobnie tego chciałeś
#include <iostream>
int main() {
size_t len = 5, step;
for (size_t i = 0; i < len; ) {
std::cout << "i = " << i << ", step? " << std::flush;
std::cin >> step;
i += step;
}
}
Jest także coś w rodzaju uprzedzenia konwencji <
, ponieważ często opiera się na zamawianiu w standardowych kontenerach operator<
, na przykład haszowanie w kilku kontenerach STL określa równość poprzez powiedzenie
if (lhs < rhs) // T.operator <
lessthan
else if (rhs < lhs) // T.operator < again
greaterthan
else
equal
Jeśli lhs
i rhs
są klasą zdefiniowaną przez użytkownika piszącą ten kod jako
if (lhs < rhs) // requires T.operator<
lessthan
else if (lhs > rhs) // requires T.operator>
greaterthan
else
equal
Implementator musi zapewnić dwie funkcje porównawcze. Tak <
stał się ulubionym operatorem.
i++
nai+=2
(na przykład), będzie działał przez bardzo długi czas (lub być może na zawsze). Teraz, ponieważ zwykle używasz<
w przypadkach, w których iterator zwiększa się o więcej niż 1, równie dobrze możesz użyć<
również w przypadku, gdy zwiększasz iterator o 1 (dla spójności).