Осторожно, я говорю о ::abs()
не std::abs()
Согласно веб-сайт cplusplus.com, abs
должен вести себя по-другому для stdlib.
h C версия, если вы включите <cmath>
Вот выдержка из этой страницы (которая имеет дело с ::abs
не std::abs
):
double abs (double x);
float abs (float x);
long double abs (long double x);
Compute absolute value
/*
Returns the absolute value of x: |x|.
These convenience abs overloads are exclusive of C++. In C, abs is only declared
in <cstdlib> (and operates on int values).
The additional overloads are provided in this header (<cmath>) for the integral types:
These overloads effectively cast x to a double before calculations
(defined for T being any integral type).
*/
В самом деле???
Я был укушен этим при переносе программы на новую платформу, так как разные компиляторы и реализация стандартных библиотек здесь отличаются.
Вот мой пример программы:
#include <iostream>
//#include <stdlib.h>//Necessary inclusion compil under linux
//You can include either cmath or math.h, the result is the same
//#include <cmath>
#include <math.h>
int main(int argc, const char * argv[])
{
double x = -1.5;
double ax = std::abs(x);
std::cout << "x=" << x << " ax=" << ax << std::endl;
return 0;
}
И вот результат под MSVC 2010:
stdlib.h
: это похоже на math.h
а также stdlib.h
всегда включены все, что вы делаетеx=-1.5 ax=1.5
(вроде бы правильно по ссылке)Теперь вот результат под OSX:
-Wall
флаг (удвоение к int не сигнализируется)! Результат тот же, если заменить g++
от llvm-g++
, Включение math.h
или же cmath
не требуется для компиляции.x=-1.5 ax=1
И наконец результат под Linux:
stdlib.h
не включен (наконец, один компилятор, который не включает stdlib
автоматически). Предупреждение о компиляции не выводится при приведении типа double -> int.x=-1.5 ax=1
Нет явного победителя здесь. Я знаю, что очевидный ответ «предпочитаю std::abs
в ::abs
«, но мне интересно
abs
должен автоматически предоставить двойную версию за пределами std
Пространство имен?math.h
тихо)?Официальные ссылки говорят … это беспорядок. Пре-С ++ 11 и С11:
Официально, в том числе <cmath>
ничего не ввел в ::
;
все функции были в std::
, Практически только
export
был менее уважаем, и разные компиляторы сделали очень
разные вещи. Если вы включили <cmath>
, ты использовал std::
везде, или то, что вы получили, варьируется от компилятора к компилятору.
C не предоставил никаких перегрузок: abs
взял int
, и был
объявлено в <stdlib.h>
, fabs
взял double
, и был
объявлено в <math.h>
,
Если вы включили <math.h>
в С ++ не понятно что ты
получил, но так как ни один из разработчиков, казалось, не заботился о
стандарт в любом случае (см. первый пункт выше) …
Грубо говоря, либо ты включил <cmath>
и с префиксом
все использует с std::
или вы включили <math.h>
, а также
используемый fabs
если вы хотели поддержку с плавающей запятой (и
различные суффиксы для типов, отличных от int
или же double
).
C ++ 11 и C11 добавили несколько новых поворотов:
<cmath>
теперь разрешено (но не обязательно) вводить
символы в ::
также. Еще одна вещь, которая может варьироваться
в зависимости от реализации. (Целью здесь было сделать
существующие реализации соответствуют.)
C имеет новый заголовок, <tgmath.h>
, который использует магию компилятора для
сделать функции в <math.h>
вести себя так, как будто они
перегружен как в C ++. (Так что это не относится к abs
, но только
в fabs
.) Этот заголовок был не был добавлен в C ++, для
очевидная причина того, что C ++ не нуждается в магии компилятора для
этот.
В общем, ситуация стала немного хуже, и мой
Рекомендации выше все еще остаются Включить либо <math.h>
а также
<stdlib.h>
и использовать abs
/fabs
и их производные (например,
labs
, fabsf
и т. д.) исключительно или включают <cmath>
, а также
использование std::abs
исключительно. Что-нибудь еще, и вы столкнетесь с
проблемы переносимости.
Других решений пока нет …