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

时间:2014-01-27 22:01:08

标签: c++ cmath

注意,我说的是::abs(),而不是std::abs()

根据cplusplus.com website,如果您包含abs

,则stdlib.应该对<cmath> h C版本的行为有所不同

以下是此页面的摘录(处理::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.hstdlib.h似乎总是包括你做的一切
  • 程序输出为:x=-1.5 ax=1.5(根据参考文献看似正确)

现在这是OSX下的结果:

  • 即使使用-Wall标志,也不会发出编译警告(未发出双重转换信号)!如果您将g++替换为llvm-g++,结果会相同。编译不需要包含math.hcmath
  • 程序输出为:x=-1.5 ax=1

最后是Linux下的结果:

  • 如果未包含stdlib.h(最后,一个编译器不自动包含stdlib),程序将无法编译。没有为double发出编译警告 - &gt; int cast。
  • 程序输出为:x=-1.5 ax=1

这里没有明显的赢家。我知道一个明显的答案是“更喜欢std::abs::abs”,但我想知道:

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

1 个答案:

答案 0 :(得分:30)

官方参考说......这是一团糟。 Pre-C ++ 11和C11:

  • 正式,包括<cmath>::中没有引入任何内容; 所有功能都在std::。实际上,只有 export不太受尊重,不同的编译器也做得很好 不同的东西。如果您添加<cmath>,则使用了std:: 无处不在,或者从编译器到编译器各种各样。

  • C没有提供任何重载:abs占用了int,而且是。{ 在<stdlib.h>中声明,fabsdouble,而且是<math.h><math.h>中声明。

  • 如果你在C ++中包含<cmath>,那么你就不清楚了 得到了,但因为没有一个实施者似乎关心 无论如何标准(参见上面第一点)......

粗略地说,要么包含std::,要么加前缀 <math.h>的所有用途,或者您包括fabs和。{ 使用int如果你想要支持浮点(和 double<cmath>以外的其他类型的各种后缀。

C ++ 11和C11增加了一些新的内容:

  • ::现在允许(但不是必需)引入 <tgmath.h>中的符号也是如此。还有一件事可以改变 取决于实施。 (这里的目标是制作 现有的实施符合。)

  • C有一个新标头<math.h>,它使用编译器魔术 使abs中的函数表现得像它们一样 像在C ++中一样重载。 (因此它不适用于fabs,但仅适用于<math.h><stdlib.h>。)此标题已将 not 添加到C ++中 C ++不需要任何编译魔术的明显原因 此

总而言之,情况已经变得更糟了,我的 上述建议仍然有效。包含abs和。{ fabs,并使用labs / fabsf及其衍生(例如{1}} <cmath>std::abs等),或者包括{{1}},和 仅使用{{1}}。还有别的,你会遇到的 可行性问题。