2014-01-27 4 views
15

Осторожно, я говорю о ::abs(), не std::abs()abs vs std :: abs, что говорит ссылка?

Согласно cplusplus.com website, abs должен вести себя по-разному для stdlib. ч версии 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:

  • Нет предупреждения компиляции не испускается под MSVC 2010, и программа будет собирать даже если вы не включают ни math.h, ни stdlib.h: кажется, что math.h и stdlib.h всегда включены, что бы вы ни делали
  • Выход программы: x=-1.5 ax=1.5 (seemi ngly правильно по ссылке)

Теперь вот результат под OSX:

  • Нет предупреждения компиляции не выделяется, даже с -Wall флагом (двойной в целое бросание не сигнализируется)! Результат будет таким же, если вы замените g++ на llvm-g++. Для компиляции не требуется включение math.h или cmath.
  • Выход программы: x=-1.5 ax=1

И, наконец, результат под Linux:

  • Программа не компилируется, если stdlib.h не входит (наконец, один компилятор, который не включает в себя stdlib автоматически). Предупреждение о компиляции не выбрано для двойного -> int cast.
  • Выход программы: x=-1.5 ax=1

Нет явного победителя здесь. Я знаю, что очевидный ответ «предпочитают std::abs к ::abs», но мне интересно:

  • Является ли сайт cplusplus.com прямо здесь, когда он говорит, что abs должна автоматически обеспечивать двойную версию за пределами std пространства имен?
  • Здесь не все компилятор и их стандартные библиотеки, кроме MSVC (хотя он включает в себя math.h молча)?
+10

'cstdlib' не является заголовком C, поэтому cplusplus.com не прав (сюрприз). Также обратите внимание, что включение 'iostream' может путать вещи, потому что оно может включать' cmath' и/или 'cstdlib', оба из которых могут вводить различные перегрузки' abs' в глобальном пространстве имен. Так избавься от этого. – juanchopanza

+0

Держитесь; мы используем 'std :: abs' или просто' :: abs'? (Используя MinGW, вышесказанное жалуется, что '' abs 'не является членом' std''; изменение на ':: abs' дает мне 1 результат. – tabstop

+2

« двойная трансляция не сигнализируется »- нет двойного к int cast в вашем коде. «Правильно ли cplusplus.com» - ** Я не знаю, **, но cplusplus.com является * печально известным * за то, что он содержит неправильную и/или вводящую в заблуждение информацию, поэтому я предполагаю, что «нет, cplusplus.com неверен ». То же самое относится к MSVC (если согласны 3 компилятора и MSVC не согласен, то очень вероятно, что MSVC ошибочен, но опять же, я не знаю, я не программист на C++.) –

ответ

23

Официальные ссылки говорят ... это беспорядок. Pre-C++ 11 и С11:

  • Официально не включая <cmath> введенного ничто в ::; все функции были выполнены в std::. Практически только export был менее уважаемым, а разные составители сделали очень разные вещи. Если вы включили <cmath>, вы использовали std:: всюду, или то, что вы меняли от компилятора к компилятору.

  • C не предусматривает каких-либо перегрузок: abs взял int, и был объявлен в <stdlib.h>, fabs взял double, и был объявлен в <math.h>.

  • Если вы включили <math.h> в C++, это не ясно, что вы получили, но так как ни один из исполнителей не казалось, заботиться о стандарт в любом случае (см первый пункт выше) ...

Грубо говоря, как вы включили <cmath> и приставкой все использования с std::, или вы включили <math.h> и используется fabs, если вы хотите поддержку с плавающей точкой (и различные суффиксы для типов O чем int или double).

C++ 11 и С11 добавили несколько новых завихрений:

  • <cmath> теперь разрешено (но не обязательно), чтобы ввести символы в ::, а также. Еще одна вещь, которая может варьироваться от в зависимости от реализации. (Цель здесь была сделать существующих реализации совместимым.)

  • C имеет новый заголовок, <tgmath.h>, который использует магию компилятора сделать функции в <math.h> ведете себя, как если бы они были перегружен, как в C++. (Таким образом, это не относится к abs, но только к fabs.) Этот заголовок был не был добавлен в C++, для очевидной причине, что C++ не требуется никакой магии компилятор для этого.

В целом, ситуация стала немного хуже, и мои рекомендации выше все еще держат. Включите либо <math.h> и <stdlib.h>, и использовать abs/fabs и их образовавшиеся (например labs, fabsf и т.д.) исключительно, или включать в себя <cmath> и использовании std::abs исключительно. Что-нибудь еще, и вы столкнетесь с проблемами portabiity.

+0

Вы правы, это беспорядок :-) Но большое спасибо за ваш подробный ответ и за историю C/C++ –

Смежные вопросы