什么是摆脱“警告C4267可能丢失数据”的最佳策略?

时间:2016-04-25 07:52:40

标签: c++ windows casting porting suppress-warnings

我将一些遗留代码从win32移植到win64。不是因为win32对象的大小太小而不能满足我们的需求,而是因为win64现在更加标准,我们希望将所有环境都移植到这种格式(我们还使用一些第三方库,在64位中提供比32位更好的性能)

我们最终得到了很多;

  

警告C4267:'参数':从'size_t'转换为'...',可能会丢失数据

主要是由于代码如:unsigned int size = v.size();其中v是STL容器。

我知道为什么警告有意义,我知道它为什么发布以及如何解决。但是,在这个具体的例子中,我们从未经历过容器大小过去超过unsigned int最大值的情况....所以当代码移植到64位环境时,没有理由出现这个问题

我们讨论过什么是最好的策略来压制那些嘈杂的警告(他们可能会隐藏我们会错过的相关警告),但是我们无法对适当的策略做出决定。

所以我在这里问这个问题,推荐的最佳策略是什么?

1。使用static_cast

使用static_cast。做unsigned int size = static_cast<unsigned int>(v.size());。我并不“喜欢”,因为我们放弃了64位容量来在容器中存储大量数据。但由于我们的代码从未达到32位的限制,所以这似乎是一个安全的解决方案......

2。将unsigned int替换为size_t

这绝对比较难,因为上面示例中的unsigned int size对象可以被设置为其他函数,保存为类属性,然后删除单行警告最终会导致数百次代码更改...

第3。禁用警告

这很可能是一个非常糟糕的主意,因为在这种情况下它也会禁用警告uint8_t size = v.size(),这肯定会导致数据丢失....

4。定义“安全演员”*功能并使用它

某事like

template <typename From, typename To> To safe_cast( const From& value )
{
    //assert( value < std::numeric_limits<To>::max() && value > std::numeric_limits<To>::min() );
    // Edit 19/05: test above fails in some unsigned to signed cast (int64_t to uint32_t), test below is better:
    assert(value == static_cast<From>(static_cast<To>(value))); // verify we don't loose information!
    // or throw....
    return static_cast<To>( value ); 
}

5。欢迎其他解决方案......

“在这种情况下使用解决方案1,但在这种情况下使用2”可能是一个很好的答案。

2 个答案:

答案 0 :(得分:8)

使用正确的类型(选项2) - 函数/接口为您定义该类型,使用它。

std::size_t size = v.size(); // given vector<>::size_type is size_t
// or a more verbose
decltype(v)::size_type size = v.size();

这是意图... 您获得了size vsize有一个类型。如果从一开始就使用了正确的类型,那就不会有问题了。

如果您稍后需要该值作为另一种类型,那么转换它; safe_cast<>是一个很好的选择,包括运行时边界检查。

选项6.使用auto

当您使用size = v.size()时,如果您不关心该类型是什么,只能使用正确的类型,

auto size = v.size();

让编译器为你努力工作。

答案 1 :(得分:0)

IFF你有时间压力让代码警告免费,我会最初禁用警告 - 你的代码用来处理这个,恕我直言,非常不太可能在你分配到32位大小的情况下你会超过它。 (集合中4个 G 值 - 我怀疑它会在正常应用中飞行。)

话虽如此,对于其他而不是集合的情况,警告肯定有其优点,所以尽量早点启用它。

第二,当启用它并修复代码时,我的优先级将是:

  • 对价值不会进一步缩小的本地人使用auto(或size_t预C ++ 11)。
  • 对于,当需要缩小时,如果您可以证明将其引入团队的开销是合理的,请使用safe_cast。 (学习,执行等)
  • 否则只需使用static_cast

    我不认为这是收藏品的问题。如果 恕我直言,对于任何正常的现实世界用例,在集合中拥有那么多数据是没有意义的。 (这并不是说可能没有你需要这么大的数据集的奇怪案例,只是你知道什么时候会这样。)

    如果您实际上没有缩小集合的数量,而是缩小其他数字,则无论如何缩小范围可能会有问题,因此您将适当地修复代码。