对于以下类型的代码,我总是会收到以下警告。
std::vector v;
for ( int i = 0; i < v.size(); i++) {
}
warning C4267: 'initializing' : conversion from 'size_t' to 'int', possible loss of data
我理解size()
返回size_t
,只是想知道忽略此警告是否安全,或者我应该创建size_t
类型的所有循环变量
答案 0 :(得分:47)
如果您可能需要在矢量中保留超过INT_MAX
个项目,请使用size_t
。在大多数情况下,它并不重要,但我使用size_t
只是为了让警告消失。
更好的是,使用迭代器:
for( auto it = v.begin(); it != v.end(); ++it )
(如果您的编译器不支持C ++ 11,请使用std::vector<whatever>::iterator
代替auto
)
C ++ 11还可以更轻松地选择最佳索引类型(如果您在某些计算中使用索引,而不仅仅是订阅v
):
for( decltype(v.size()) i = 0; i < v.size(); ++i )
答案 1 :(得分:18)
什么是size_t
?
size_t
对应于语言运算符sizeof
返回的整数数据类型,并在头文件(以及其他)中定义为unsigned integral type
。
是否可以将size_t
投放到int
?
如果您确定尺寸永远不会是>,则可以使用演员表。比INT_MAX
。
如果您正在尝试编写可移植代码,则不安全,因为
size_t
中的{p> 64 bit Unix
为64 bits
size_t
中的64 bit Windows
为32 bits
因此,如果您将代码从Unix移植到WIndows,如果上面是环境,您将丢失数据。
建议的答案
考虑到警告,建议是i
unsigned integral type
,或者更好地将其用作size_t
类型。
答案 2 :(得分:11)
可以安全地忽略此警告,或者我应该创建size_t
类型的所有循环变量
没有。你正在打开一类整数溢出攻击。如果向量大小大于MAX_INT
(并且攻击者有办法使这种情况发生),您的循环将永远运行,从而导致拒绝服务。
从技术上讲,std::vector::size
会返回std::vector::size_type
。
您应该为循环计数器变量使用正确的符号。 (实际上,对于大多数用途,无论如何都需要无符号整数而不是有符号整数)
答案 3 :(得分:5)
问题在于您混合了两种不同的数据类型。在某些体系结构中,size_t
是32位整数,而其他体系结构是64位。您的代码应该正确处理两者。
因为size()
返回size_t
( not int ),那么这应该是您与之比较的数据类型。
std::vector v;
for ( size_t i = 0; i < v.size(); i++) {
}
答案 4 :(得分:5)
以下是Bjarne Stroustrup的另一个观点: http://www.stroustrup.com/bs_faq2.html#simple-program
for (int i = 0; i<v.size(); ++i) cout << v[i] << '\n';
是的,我知道我可以声明我是一个vector :: size_type 而不是简单的int来安静一些超级可疑的警告 编译器,但在这种情况下,我认为这太迂腐了 分心。
这是一种权衡。如果您担心v.size()可能超过2,147,483,647,请使用size_t。如果你在循环中使用i不仅仅是查看向量内部,而是关注微妙的有符号/无符号相关错误,请使用int。根据我的经验,后一个问题比前者更普遍。您的经历可能会有所不同。