如何避免 std::abs 的意外结果?
How can I avoid unexpected results from std::abs?
我遇到了几个不同的例子,说明std::abs
可以给出意想不到的结果:
- 这个问题(在 std::abs 函数上(指出
<cstdlib>
为整型提供重载,而<cmath>
为浮点类型提供重载。未能包含正确的标头会给出未定义的行为,允许编译器以静默方式接受该行为 - C++缺陷报告2735指出C++11和C++14标准在技术上要求
std::abs(short)
返回double
,尽管大多数编译器忽略了相关措辞并返回int
。此问题的解决方案表明措辞已在 C++17 中更改,以便std::abs(short)
返回int
- 这个问题的答案(我什么时候使用晶圆厂,什么时候使用std::abs就足够了? 指出依赖
std::abs
可能会导致难以发现的错误,因为(在现代C++中(引入std::abs
的标头被允许引入全局abs
函数(可能具有也可能没有相同的重载(,并且很容易意外使用abs
而不是std::abs
我知道的修复程序是:
- 避免未定义的行为:如果评估
std::abs([integral type])
,请包括<cstdlib>
,如果评估std::abs([floating point type])
,请包括<cmath>
- 两个选项:
- 使用 C++17 或 (C++11( 之前的版本
- 解决
std::abs(short)
可能会返回int
或double
的事实,具体取决于编译器是否符合 C++11/C++14 标准
- 两个选项:
- 将 gcc 的标志传递
–Wconversion
以便像abs(2.0)
这样的调用在编译时触发警告 - 使用一个技巧(改编自 n.m. 的答案(使用 cmath 时禁用 math.h 废话((使全局
abs
模棱两可
- 将 gcc 的标志传递
把戏:
namespace neveruse{
int abs(int);
}
using namespace neveruse;
问题:是否有理由选择问题 3 的解决方案之一而不是另一个?这些修复程序是否引入了我需要注意的其他潜在问题?
创建自己的头文件,该文件定义一个inline
函数absolute
该函数又包含所有正确的标头并修复返回类型的错误,并调用std::abs
。
然后,不要使用abs
或std::abs
(或任何名为abs
的令牌(。 在 git 提交(或您使用的任何版本管理系统(中强制执行此操作,而不是在该文件中。
相关文章:
- 尝试将字符串/字符转换为整数会产生意外结果
- RapidXML - 代码创建意外结果
- 类中静态函数C++意外结果
- 指针数组中的意外结果
- 使用指针访问数组元素时出现意外结果
- 使用 sprintf 和 %g 将双精度转换为字符串的意外结果
- C++:比较运算符>和字符串文本的意外结果
- 具有意外结果的 C++ 闭包
- yaml-cpp 比较的意外结果
- 每次都出现意外结果
- 在 Qt 中解析嵌套的 JSON 时出现意外结果(数组不存在)
- 如何避免 std::abs 的意外结果?
- 使用嵌套 if 语句的意外结果
- A ^= B ^= A ^= B;C# Visual Studio 中的意外结果
- 逻辑错误,我将获得意外结果
- 在 c++ 中使用异步的意外结果
- 从函数的返回值将元素C++存储到 std::vector 中时出现意外结果
- 执行递增和递减时"cout"链接会产生意外结果
- OpenCL - 内核方法返回意外结果
- C++使用 std::get_time 解析 YYMMDD ISO 8601 日期字符串会得到意外结果