我将一些遗留代码从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”可能是一个很好的答案。
答案 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
v
而size
有一个类型。如果从一开始就使用了正确的类型,那就不会有问题了。
如果您稍后需要该值作为另一种类型,那么转换它; 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
:
我不认为这是收藏品的问题。如果 恕我直言,对于任何正常的现实世界用例,在集合中拥有那么多数据是没有意义的。 (这并不是说可能没有你需要这么大的数据集的奇怪案例,只是你知道什么时候会这样。)
如果您实际上没有缩小集合的数量,而是缩小其他数字,则无论如何缩小范围可能会有问题,因此您将适当地修复代码。