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

jpo*_*o38 9 c++ windows porting casting 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 intsize_t

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

3.禁用警告

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

4.定义"安全演员"*功能并使用它

像这样的东西:

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 ); 
}
Run Code Online (Sandbox Code Playgroud)

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

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

Nia*_*all 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();
Run Code Online (Sandbox Code Playgroud)

它符合意图......你得到了它size,v并且size有一种类型.如果从一开始就使用了正确的类型,这不会是一个问题.

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

选项6.使用 auto

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

auto size = v.size();
Run Code Online (Sandbox Code Playgroud)

让编译器为您完成艰苦的工作.

  • @Niall:当然,我认为我们将卷起袖子并将所有`unsigned int`更改为`size_t` .... (2认同)