首页 > 解决方案 > 处理可能丢失数据的编译器警告的最优雅方法是什么

问题描述

在我们的大型 C++ 项目中,我们力求没有警告,但人们通常对此很懒惰。我不断修复的一件事是来自如下代码的警告:

sizex = sizey = 32 * c_scale;

给予

警告 C4244:“=”:从“double”转换为“i16”,可能丢失数据

其中 sizex 和 sizey 是 i16 类型,而 c_scale 是双精度类型。

所以我不断将这样的代码行更改为

sizex = sizey = i16(32 * c_scale);

使警告消失。

我会说这会降低代码的可读性,所以我对此并不满意,但在我看来,这比禁用警告要好,也比让一堆警告掩盖可能更严重的警告要好。

任何人都有更优雅或不同的方式来处理这种情况?

标签: c++compiler-warnings

解决方案


一些有用的可读性和可维护性指南:

使用标准类型

想象一下我加入了你的项目。我不知道 ani16是什么,您链接的任何库也不知道。但我确实知道 astd::int16_t是什么(在 中找到<cstdint>)。图书馆作家也是如此。

隐藏抽象背后的细节

您在此处描述的操作是将整数缩放某个因子(比如双倍?)。魔鬼在细节中。您不能在不丢失数据的情况下将 double 转换回整数,因此您必须恢复为强制转换,这看起来很混乱,并且会让未来的维护者想知道您在做什么。

所以让我们构建一个抽象:

inline
auto scale_and_round_down(std::int16_t value, double scale) -> std::uint16_t
{
    auto scaled_value = value * scale;  // answer will be a double
    return std::int16_t(value * scale); // round down to nearest int
}

现在我们的代码变成了:

sizex = sizey = scale_and_round_down(32, c_scale);

毫无疑问地表达了意图。在发布版本中, scale_and_round_down将被内联。您不会为这样的抽象支付任何性能成本。


推荐阅读