【发布时间】:2018-10-16 03:00:06
【问题描述】:
我遇到了几个不同的例子,说明std::abs 可以产生意想不到的结果:
- 这个问题(On the std::abs function)指出
<cstdlib>为整数类型提供重载,而<cmath>为浮点类型提供重载。未能包含正确的标头会导致未定义的行为,允许编译器静默接受 - C++ Defect report 2735 指出 C++11 和 C++14 标准在技术上要求
std::abs(short)返回double,尽管大多数编译器会忽略相关措辞并返回int。此问题的解决方法表明 C++17 中的措辞已更改,因此std::abs(short)返回int - 这个问题的答案 (When do I use fabs and when is it sufficient to use std::abs?) 指出依赖
std::abs会导致难以发现的错误,因为(在现代 C++ 中)引入std::abs的标头允许引入全局abs函数(可能有也可能没有相同的重载),很容易不小心使用abs而不是std::abs
我知道的修复是:
- 避免未定义的行为:如果评估
std::abs([integral type]),则包括<cstdlib>,如果评估std::abs([floating point type]),则包括<cmath> - 两个选项:
- 使用 C++17 或 pre-(C++11)
- 根据编译器是否符合 C++11/C++14 标准,解决
std::abs(short)可能返回int或double的问题
- 两个选项:
- 将标志
–Wconversion传递给 gcc,以便像abs(2.0)这样的调用在编译时触发警告 - 使用技巧(改编自 n.m. 对 (Disable math.h crap when working with cmath) 的回答)使全局
abs模棱两可
- 将标志
技巧:
namespace neveruse{
int abs(int);
}
using namespace neveruse;
问题:是否有理由更喜欢问题 3 的解决方案之一?这些修复中的任何一个是否会引入我需要注意的其他潜在问题?
【问题讨论】:
-
我经常用
auto i_am_also_a_float = fabsf(i_am_a_float); -
您能否准确说明您要避免的缺陷。这个问题是否只询问 std::abs(short) 返回双精度和整数的问题? (你还想要哪个?)
-
我很想知道问题 3 的解决方案是否更好,以及问题 1 或 2 的任何解决方案是否有我可能没有考虑过的副作用(例如容易犯类似忘记 std:: 的其他错误。
-
我认为这个技巧没有任何帮助,因为它会阻止 ::abs(...) 的使用,而语言缺陷会影响 std::abs(.. .)
-
“来自 std::abs 的意外结果”包括
abs(INT_MIN)。
标签: c++ language-lawyer