c++ - abs vs std::abs,引用说明了什么?

标签 c++ cmath

小心,我说的是::abs() ,而不是 std::abs()

根据cplusplus.com website , 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无论您做什么,总是包含在其中
  • 程序输出为:x=-1.5 ax=1.5 (根据引用资料似乎是正确的)

现在是 OSX 下的结果:

  • 即使使用 -Wall,也不会发出编译警告标志(没有信号转换为 int 的 double )!如果替换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)?

最佳答案

官方引用资料说……这是一团糟。 C++11 和 C11 之前的版本:

  • 官方,包括<cmath> :: 中没有引入任何内容; 所有的功能都在std:: .实际上,只有 export不太受尊重,不同的编译器做得非常好 不同的东西。如果您包括 <cmath> ,您使用了 std:: 到处都是,或者你得到的东西因编译器而异。

  • C 没有提供任何重载:abs拍了int , 并且是 在 <stdlib.h> 中声明, fabs拍了double , 并且是 在 <math.h> 中声明.

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

粗略地说,要么包括<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只。其他任何事情,你都会遇到 便携性问题。

关于c++ - abs vs std::abs,引用说明了什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21392627/

相关文章:

c++ - 结构变量成员后的花括号是什么意思?

c++ - 定义不返回值的 C++ 转换运算符

c++ - 警告 C4121 行为和结构对齐 (Visual Studio 2010)

algorithm - 为什么我们应该在 <algorithm> 头的函数之前使用 std 命名空间而不应该在 <cmath> 头的函数之前使用它?

c++ - 对 abs(double) 的模棱两可的重载调用

c++ - 如何使用数组将多个字符串文字传递给函数(无 vector )

c# - 消息模式下的 NamedPipeClientStream 永远不会将 IsMessageComplete 设置为 true

c++ - 在 cmath 库中使用函数时遇到问题

c++ - C++ 中的数学接口(interface)与 cMath

c++ - Clang: 'cmath' 找不到文件