Zakładam to abs
i fabs
zachowuję się inaczej podczas używania math.h
. Ale kiedy używam just cmath
i std::abs
, czy muszę używać std::fabs
lub fabs
? Czy nie jest to zdefiniowane?
Zakładam to abs
i fabs
zachowuję się inaczej podczas używania math.h
. Ale kiedy używam just cmath
i std::abs
, czy muszę używać std::fabs
lub fabs
? Czy nie jest to zdefiniowane?
Odpowiedzi:
W C ++ zawsze wystarczy użyć std::abs
; jest przeciążony dla wszystkich typów liczbowych.
W C abs
działa tylko na liczbach całkowitych i potrzebujesz fabs
wartości zmiennoprzecinkowych. Są one dostępne w C ++ (wraz z całą biblioteką C), ale nie ma potrzeby ich używania.
int
wersji z biblioteki C, istnieje przeciążenia dla long
, float
, double
i long double
. Punkt 26.2.7 definiuje również przeciążenie dla complex
.
std::
i po prostu go użyjesz abs
, twój kod będzie działał zgodnie z oczekiwaniami w systemie Windows, ale będzie używał int
wersji pod Linuksem, co może być niezwykle trudne do debugowania.
Nadal można używać argumentów fabs
for double
i float
. Wolę to, ponieważ zapewnia to, że jeśli przypadkowo usunę std::
element abs
, zachowanie pozostanie takie samo dla danych zmiennoprzecinkowych.
Właśnie spędziłem 10 minut na debugowaniu tego właśnie problemu, z powodu mojego własnego błędu użycia abs
zamiast std::abs
. Zakładałem, using namespace std;
że wywnioskuje, std::abs
ale tak się nie stało i zamiast tego użyłem wersji C.
W każdym razie uważam, że warto używać fabs
zamiast abs
zmiennoprzecinkowych danych wejściowych, aby jasno udokumentować swój zamiar.
std::abs
zawsze wydaje się być wywoływane (a nie wersja C abs
) podczas dzwonienia, abs
o ile using namespace std;
jest to wyjaśnione w początek. Nie wiem, czy jest to specyficzne dla kompilatora.
Jest jeszcze jeden powód, dla którego warto std::fabs
jawnie zalecać wprowadzanie danych zmiennoprzecinkowych.
Jeśli zapomnisz dołączyć <cmath>, std::abs(my_float_num)
możesz std::abs(int)
zamiast std::abs(float)
. Trudno to zauważyć.
„abs” i „fabs” są identyczne tylko dla typów zmiennoprzecinkowych C ++, gdy można je przetłumaczyć bez niejednoznacznych komunikatów o przeciążeniu.
Używam g ++ (g ++ - 7). Wraz z użyciem szablonu, a zwłaszcza przy używaniu mpreal, istnieją przypadki z twardymi komunikatami „niejednoznacznego przeciążenia” -abs(static_cast<T>(x))
nie zawsze to rozwiązuje. Kiedy abs jest niejednoznaczny, są szanse, że fabs działa zgodnie z oczekiwaniami. W przypadku sqrt nie znalazłem takiej prostej ucieczki.
Od tygodni ciężko zmagam się z „nieistniejącymi problemami” w C ++. Aktualizuję stary program C ++ do C ++ 14, aby korzystać z szablonów w większym i lepszym stopniu niż było to możliwe wcześniej. Często ten sam parametr szablonu może być w rzeczywistości dowolnym standardowym typem zmiennoprzecinkowym, typem złożonym lub typem klasy. Dlaczego zawsze, długi podwójny akt był nieco rozsądniejszy niż inne typy. Wszystko działało, a wcześniej włączyłem mpreal. Potem ustawiałem domyślny typ float na mpreal i dostałem zalew błędów składniowych. To dało tysiące niejednoznacznych przeciążeń, np. Dla abs i sqrt, wzywając do różnych rozwiązań. Niektórzy potrzebowali przeciążonych funkcji pomocy, ale poza szablonem. Trzeba było pojedynczo zastąpić tysiące zastosowań 0,0L i 1,0L dokładnym typem stałym przy użyciu Zero lub One lub type_cast - automatyczna definicja konwersji niemożliwa z powodu niejednoznaczności.
Do maja bardzo fajnie wydawało mi się istnienie niejawnych konwersji. Ale o wiele prościej byłoby bez żadnych i mieć typozapisywać stałe z bezpiecznymi jawnymi typami typu_cast do dowolnego innego standardowego typu stałego.