Я предполагаю, что absи fabsпри использовании ведут себя иначе math.h. Но когда я использую только cmathи std::abs, нужно ли мне использовать std::fabsили fabs? Или это не определено?
Я предполагаю, что absи fabsпри использовании ведут себя иначе math.h. Но когда я использую только cmathи std::abs, нужно ли мне использовать std::fabsили fabs? Или это не определено?
Ответы:
В C ++ всегда достаточно использовать std::abs; он перегружен для всех числовых типов.
В C absработает только с целыми числами, а вам нужны fabsзначения с плавающей запятой. Они доступны в C ++ (вместе со всей библиотекой C), но в их использовании нет необходимости.
intверсии из библиотеки C, есть перегруженные для long, float, doubleи long double. В пункте 26.2.7 также определяется перегрузка для complex.
std::и просто используете abs, ваш код будет работать в Windows, как ожидалось, но будет использовать intверсию в Linux, что может быть невероятно сложно отладить.
По-прежнему можно использовать аргументы fabsfor doubleи float. Я предпочитаю это , потому что это гарантирует , что , если я случайно обирать std::выключить abs, что поведение остается неизменным с плавающей точкой входа.
Я просто потратил 10 минут на отладку этой самой проблемы из-за моей собственной ошибки в использовании absвместо std::abs. Я предполагал, что это using namespace std;будет вывод, std::absно этого не произошло, и вместо этого использовал версию C.
В любом случае, я считаю, что лучше использовать fabsвместо absввода с плавающей запятой как способ четко задокументировать свое намерение.
std::absвсегда вызывается перегруженный (а не C-версия abs) при вызове, absесли using namespace std;это объяснено в начало. Я не знаю, зависит ли это от компилятора.
Есть еще одна причина std::fabsявно рекомендовать ввод с плавающей запятой.
Если вы забыли включить <CMATH>, ваш std::abs(my_float_num)может быть std::abs(int)вместо std::abs(float). Это сложно заметить.
«abs» и «fabs» идентичны только для типов с плавающей запятой C ++, когда они могут быть переведены без неоднозначных сообщений о перегрузке.
Я использую g ++ (g ++ - 7). Вместе с использованием шаблонов и особенно при использовании mpreal бывают случаи с жесткими сообщениями о "неоднозначной перегрузке" - abs(static_cast<T>(x))не всегда это решает. Когда abs неоднозначен, есть вероятность, что fabs работает должным образом. Для sqrt я не нашел такого простого выхода.
С недели я трудно бороться на C ++ «не существующих проблем». Я обновляю старую программу C ++ до C ++ 14 для более широкого и лучшего использования шаблонов, чем это было возможно раньше. Часто один и тот же параметр шаблона может быть любым стандартным типом с плавающей запятой, сложным типом или типом класса. Да и вообще, длинный дубль действовал несколько разумнее, чем другие типы. Все работало, и раньше я включил mpreal. Затем я установил тип float по умолчанию на mpreal и получил массу синтаксических ошибок. Это дало тысячи неоднозначных перегрузок, например, для abs и sqrt, требующих различных решений. Некоторым требовались перегруженные справочные функции, но не по шаблону. Пришлось заменить по отдельности тысячу использований 0.0L и 1.0L точным типом константы с использованием Zero или One или type_cast - автоматическое определение преобразования невозможно из-за двусмысленности.
До мая я находил очень приятным наличие неявных преобразований. Но гораздо проще было бы без них и иметь константы с сохранением типов с безопасным явным преобразованием типа в любой другой стандартный тип константы.