繁体   English   中英

abs vs std::abs,参考说明了什么?

[英]abs vs std::abs, what does the reference say?

当心,我说的是::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 下的结果:

  • 在 MSVC 2010 下不会发出编译警告,即使您既不包含 math.h 也不包含stdlib.h程序也会编译:似乎无论您做什么,都始终包含math.hstdlib.h
  • 程序output为: x=-1.5 ax=1.5 (根据参考貌似正确)

现在这是 OSX 下的结果:

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

最后是Linux下的结果:

  • 如果不包含stdlib.h ,程序将无法编译(最后,一个不自动包含stdlib的编译器)。 对于 double -> int 强制转换,不会发出编译警告。
  • 程序 output 为: x=-1.5 ax=1

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

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

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

  • 正式,包括<cmath>中介绍什么:: ; 所有函数都在std:: 实际上,只有export不那么受尊重,不同的编译器做了很多不同的事情。 如果你包含<cmath> ,你使用std:: everywhere,或者你从编译器到编译器的变化。

  • C没有提供任何重载: abs接受了一个int ,并在<stdlib.h>声明, fabsdouble ,并在<math.h>声明。

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

粗略地说,要么包含<cmath> ,要么使用std::作为所有用法的前缀,要么包含<math.h> ,如果你想要支持浮点(以及除int以外的类型的各种后缀),则使用fabsdouble )。

C ++ 11和C11增加了一些新的曲折:

  • 现在允许<cmath> (但不是必需的)在::引入符号。 还有一件事可能因实施而异。 (这里的目标是使现有的实现符合要求。)

  • C有一个新的头文件<tgmath.h> ,它使用编译器魔术使<math.h>的函数表现得像在C ++中一样重载。 (因此,并不适用于abs ,但只fabs 。)这个头没有被添加到C ++,明显的原因是C ++并不需要为这个任何编译器的魔力。

总而言之,情况变得更糟,我的建议仍然有效。 包括<math.h><stdlib.h> ,并使用abs / fabs及其派生的(例如labsfabsf等),或者包含<cmath> ,并且只使用std::abs 还有别的,你会遇到可行性问题。

我被这个错误困扰了半天......:我在我的代码中使用了 abs(a double value):但结果不是预期的。 直到我将 abs 更改为 std.:abs(上面的双精度值)。 所有结果都匹配。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM