我将一些遗留代码从 win32 移植到 win64。不是因为 win32 对象大小对我们的需求来说太小了,而是因为 win64 现在更标准了,我们希望将所有环境移植到这种格式(我们还使用一些 3rd 方库,在 64 位中提供比在 32 位中更好的性能) .
我们最终得到了很多;
warning C4267: 'argument': conversion from 'size_t' to '...', possible loss of data
主要是由于这样的代码: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)- 函数/接口(interface)为您定义了该类型,请使用它。
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();
让编译器为您完成繁重的工作。
关于c++ - 摆脱 "warning C4267 possible loss of data"的最佳策略是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36834799/