abs vs std :: abs,引用说什么?

Pas*_* T. 24 c++ cmath

当心,我在说::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).
*/
Run Code Online (Sandbox Code Playgroud)

真???

在将程序移植到新平台时,我一直被这种方式所困扰,因为不同的编译器和标准库实现在这里有所不同.

这是我的示例程序:

#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;
}
Run Code Online (Sandbox Code Playgroud)

以下是MSVC 2010下的结果:

  • 在MSVC 2010下不会发出编译警告,即使您既不包含math.h也不包含该程序,程序将编译stdlib.h:它似乎math.h并且stdlib.h总是包含在您执行的任何操作中
  • 程序输出为:( x=-1.5 ax=1.5根据参考看似正确)

现在这是OSX下的结果:

  • 即使使用-Wall标志也没有发出编译警告(没有发出双向int cast信号)!如果替换g++为,结果是相同的llvm-g++.包含math.hcmath不需要编译.
  • 程序输出是: x=-1.5 ax=1

最后是Linux下的结果:

  • 如果stdlib.h不包括该程序将不编译(最后,一个编译器不stdlib自动包含).没有为double - > int cast发出编译警告.
  • 程序输出是: x=-1.5 ax=1

这里没有明显的赢家.我知道,一个明显的答案是"宁可std::abs::abs",但我不知道:

  • 当cplusplus.com网站说它abs应该自动提供std名称空间之外的双重版本时,它是否就在这里?
  • 除了MSVC之外,所有编译器及其标准库都是错误的(尽管它包括math.h静默)?

Jam*_*nze 34

官方的参考文献说......这是一团糟.前C++ 11和C11:

  • 正式,包括<cmath>介绍什么::; 所有的功能都在std::.实际上,只是 export不那么受尊重,不同的编译器做了很多不同的事情.如果你包含<cmath>,你std:: 在任何地方使用,或者你从编译器到编译器的各种变化.

  • C没有提供任何重载:abs接受int,并且被声明<stdlib.h>,fabs接受double,并被宣布进入<math.h>.

  • 如果你包含<math.h>在C++中,你不清楚你得到了什么,但是因为没有任何实现者似乎关心标准(参见上面的第一点)......

粗略地说,如果您想要支持浮点(以及除or之外的其他类型的各种后缀),要么包含,要么<cmath>为所有用途添加前缀std::,或者包含<math.h>和使用.fabsintdouble

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专门.还有别的,你会遇到可行性问题.