size_t vs int警告

Avi*_*ash 43 c++ stl visual-c++

对于以下类型的代码,我总是得到以下警告.

std::vector v;
for ( int i = 0; i < v.size(); i++) {
}
Run Code Online (Sandbox Code Playgroud)

warning C4267: 'initializing' : conversion from 'size_t' to 'int', possible loss of data

我明白size()返回size_t,只是想知道是否可以安全地忽略此警告,或者我应该创建所有类型的循环变量size_t

Ben*_*igt 48

如果您可能需要INT_MAX在矢量中保留多个项目,请使用size_t.在大多数情况下,它并不重要,但我size_t只是用来使警告消失.

更好的是,使用迭代器:

for( auto it = v.begin(); it != v.end(); ++it )
Run Code Online (Sandbox Code Playgroud)

(如果您的编译器不支持C++ 11,请使用std::vector<whatever>::iterator代替auto)

C++ 11也使得选择最佳索引类型变得更容易(如果你在某些计算中使用索引,而不仅仅是为了下标v):

for( decltype(v.size()) i = 0; i < v.size(); ++i )
Run Code Online (Sandbox Code Playgroud)

  • @Mark:也许,也许不是.如果您需要索引变量,则基于范围的循环不那么有吸引力.某些操作也需要迭代器,例如`insert()`. (2认同)

Alo*_*ave 17

什么是size_t
size_t对应于语言运算符返回的整数数据类型,sizeof并在头文件(以及其他)中定义为unsigned integral type.

它是好投size_tint
如果您确定大小永远不会超过,则可以使用强制转换INT_MAX.

如果您正在尝试编写可移植代码,则不安全,因为,

size_t64 bit Unix64 bits
size_t64 bit Windows32 bits

因此,如果您将代码从Unix移植到WIndows,如果上面是环境,您将丢失数据.

建议的答案

鉴于警告,建议是使iunsigned integral type甚至更好的使用它作为类型size_t.

  • 64位Windows中的`size_t`是64位.你想的是"长".他应该使用的是std :: vector <T> :: size_type,或者更好的是迭代器. (24认同)

Bil*_*eal 11

这样可以安全地忽略这个警告,或者我应该创建size_t类型的所有循环变量

不,你正在打开一类整数溢出攻击.如果向量大小大于MAX_INT(攻击者有办法使其发生),您的循环将永远运行,从而导致拒绝服务的可能性.

但从技术上讲,std::vector::size回报std::vector::size_type.

您应该为循环计数器变量使用正确的符号.(实际上,对于大多数用途,您希望无符号整数而不是循环的有符号整数)


tyl*_*erl 6

问题是你混合了两种不同的数据类型.在某些体系结构上,size_t是32位整数,在其他体系结构上是64位.您的代码应该正确处理两者.

因为size()返回一个size_t(不是int),那么它应该是你比较它的数据类型.

std::vector v;
for ( size_t i = 0; i < v.size(); i++) {
}
Run Code Online (Sandbox Code Playgroud)


Jon*_*Jon 5

以下是Bjarne Stroustrup的另一个观点:http: //www.stroustrup.com/bs_faq2.html#simple-program

for (int i = 0; i<v.size(); ++i) cout << v[i] << '\n';
Run Code Online (Sandbox Code Playgroud)

是的,我知道我可以声明我是一个vector :: size_type而不是普通的int来安静来自一些超级可疑的编译器的警告,但在这种情况下,我认为这太迂腐和分散注意力.

这是一种权衡.如果您担心v.size()可能超过2,147,483,647,请使用size_t.如果你在循环中使用i不仅仅是查看向量内部,而是关注微妙的有符号/无符号相关错误,请使用int.根据我的经验,后一个问题比前者更普遍.您的经历可能有所不同

另请参阅为什么size_t未签名?.

  • 我认为Stroustrup的建议实际上只适用于初学者,而不是让他们更加困惑(即"学期开始"型人).我认为在任何生产代码(以及后来的讲座)中都应该教导使用std :: size_t. (3认同)