#include <iostream>
#include <string>
#include <vector>
#include <sstream>
using namespace std;
int main() {
vector<double> vector_double;
vector<string> vector_string;
...
while (cin >> sample_string)
{
...
}
for(int i = 0; i <= vector_string.size(); i++)
{
....
}
for (int i = 0; i < vector_double.size(); i++)
....
return 0;
}
答案 0 :(得分:15)
为什么
-Wsign-compare
会出现警告?
作为警告的名称及其文本暗示,问题在于您要比较有符号整数和无符号整数。通常认为这是一次意外。
为了避免此警告,您只需确保<
(或任何其他比较运算符)的两个操作数都已签名或两者都未签名。
我怎么能做得更好?
编写for
循环的惯用方法是在第一个语句中初始化计数器和限制:
for (std::size_t i = 0, max = vec.size(); i != max; ++i)
这样可以在每次迭代时保存重新计算size()
。
您也可以(也可能应该)使用迭代器而不是索引:
for (auto it = vec.begin(), end = vec.end(); it != end; ++it)
auto
这是std::vector<int>::iterator
的简写。迭代器适用于任何类型的容器,而索引将您限制为C阵列,deque
和vector
。
答案 1 :(得分:7)
这是因为vector类中的.size()函数不是int类型,而是vector :: size_type
使用或auto i = 0u
,消息应该消失。
答案 2 :(得分:3)
int
默认签名 - 相当于撰写signed int
。您收到警告的原因是因为size()
返回的vector::size_type
很可能是未签名的。{/ p>
由于signed int
和unsigned int
拥有不同的值范围,因此存在潜在危险。 signed int
可以保存–2147483648
到2147483647
之间的值,而unsigned int
可以保存0
到4294967295
之间的值(假设int
是{{1}} 32位)。
答案 3 :(得分:2)
您的变量i
是一个整数,而返回size
的向量的Allocator::size_type
成员函数最有可能返回size_t
,这几乎总是实现为一些大小的unsigned int。
答案 4 :(得分:2)
将int i
设为size_type i
std::vector::size()
将返回size_type
unsigned int
,因为大小不能为-ve
警告显然是因为您正在将有符号整数与无符号整数进行比较。
答案 5 :(得分:2)
经过这么多答案后回答,但没有人注意到循环结束..所以,这是我的完整答案:
i
的类型更改为unsigned
,auto
(对于C ++ 11)或std::vector< your_type >::size_type
for
作为索引,则i
循环会出现段错误 - 您必须从0
循环到size-1
。所以,把它改成为for( std::vector< your_type >::size_type i = 0; i < vector_xxx.size(); ++i )
<
,而不是<=
;我建议不要将<=
与.begin() - 1
一起使用,因为您可以使用0大小的向量而将有问题:))。iterator
。这将使容器类型的未来更容易更改(当然,如果您不需要确切的位置作为数字)。所以,我会这样写:for( std::vector< your_type >::iterator iter = vector_XXX.begin();
iter != vector_XXX.end();
++iter )
{
//..
}
答案 6 :(得分:2)
您收到此警告是因为C ++中容器的大小是无符号类型,并且混合有符号/无符号类型是危险的。
我通常做的是
for (int i=0,n=v.size(); i<n; i++)
....
在我看来,这是使用索引的最佳方式,因为对索引使用无符号类型(或容器的大小)是一个逻辑错误。
仅当您关心位表示以及何时要在溢出时使用模/(2 ** n)行为时,才应使用无符号类型。仅仅因为值永远不是负数而使用无符号类型是无意义的。
对大小或索引使用无符号类型的典型错误是例如
// Draw all lines between adjacent points
for (size_t i=0; i<pts.size()-1; i++)
drawLine(pts[i], pts[i+1]);
当点数组为空时,上面的代码是UB,因为在C ++中0u-1
是一个巨大的正数。
C ++使用无符号类型表示容器大小的原因是因为选择它是16位计算机的历史遗产(IMO给出了带有无符号类型的C ++语义,即使在那时它也是错误的选择)。
答案 7 :(得分:2)
我通常会这样解决:
for(int i = 0; i <= (int)vector_string.size(); i++)
我使用C风格的强制转换,因为它比C ++ static_cast<int>()
更短,更易读,并且完成同样的事情。
这里有可能出现溢出,但前提是你的矢量大小大于最大int
,通常是2147483647.我生命中从来没有过大的矢量。如果甚至有可能使用更大的向量,那么建议size_type
的答案之一会更合适。
我不担心在循环中反复调用size()
,因为它可能是对成员变量的内联访问,不会引入任何开销。
答案 8 :(得分:1)
声明'size_t i'对我来说运作良好。
答案 9 :(得分:0)
std::cout << -1U << std::endl;
std::cout << (unsigned)-1 << std::endl;
4294967295
std::cout << 1 << std::endl;
std::cout << (signed)1 << std::endl;
1
std::cout << (unsigned short)-1 << std::endl;
65535
std::cout << (signed)-1U << std::endl;
std::cout << (signed)4294967295 << std::endl;
-1
取消索引变量的签名
unsigned int index;
index < vecArray.size() // size() would never be negative
答案 10 :(得分:0)
有些答案建议使用auto
,但由于int
是从整数文字推导出的默认类型,因此无法使用。在c++23之前,您必须明确指定cstddef标头中定义的类型std::size_t
for(std::size_t i = 0; i <= vector_string.size(); i++)
{
....
}
在c ++ 23中,添加了整数zu,motivation的确可以推断出正确的类型。
for(auto i = 0zu; i <= vector_string.size(); i++)
{
....
}
但不幸的是,尚无compiler support此功能。