如何避免 std::abs 的意外结果?

How can I avoid unexpected results from std::abs?

本文关键字:意外 结果 abs 何避免 std      更新时间:2023-10-16

我遇到了几个不同的例子,说明std::abs可以给出意想不到的结果:

  1. 这个问题(在 std::abs 函数上(指出<cstdlib>为整型提供重载,而<cmath>为浮点类型提供重载。未能包含正确的标头会给出未定义的行为,允许编译器以静默方式接受该行为
  2. C++缺陷报告2735指出C++11和C++14标准在技术上要求std::abs(short)返回double,尽管大多数编译器忽略了相关措辞并返回int。此问题的解决方案表明措辞已在 C++17 中更改,以便std::abs(short)返回int
  3. 这个问题的答案(我什么时候使用晶圆厂,什么时候使用std::abs就足够了? 指出依赖std::abs可能会导致难以发现的错误,因为(在现代C++中(引入std::abs的标头被允许引入全局abs函数(可能具有也可能没有相同的重载(,并且很容易意外使用abs而不是std::abs

我知道的修复程序是:

  1. 避免未定义的行为:如果评估std::abs([integral type]),请包括<cstdlib>,如果评估std::abs([floating point type]),请包括<cmath>
  2. 两个选项:
    • 使用 C++17 或 (C++11( 之前的版本
    • 解决std::abs(short)可能会返回intdouble的事实,具体取决于编译器是否符合 C++11/C++14 标准
  3. 两个选项:
    • 将 gcc 的标志传递–Wconversion以便像abs(2.0)这样的调用在编译时触发警告
    • 使用一个技巧(改编自 n.m. 的答案(使用 cmath 时禁用 math.h 废话((使全局abs模棱两可

把戏:

namespace neveruse{
int abs(int);
}
using namespace neveruse;

问题是否有理由选择问题 3 的解决方案之一而不是另一个?这些修复程序是否引入了我需要注意的其他潜在问题?

创建自己的头文件,该文件定义一个inline函数absolute该函数又包含所有正确的标头并修复返回类型的错误,并调用std::abs

然后,不要使用absstd::abs(或任何名为abs的令牌(。 在 git 提交(或您使用的任何版本管理系统(中强制执行此操作,而不是在该文件中。