Usamos o tipo Inteiro para representar variáveis de índice na maioria das vezes. Mas, em algumas situações, somos forçados a escolher
std::vector<int> vec;
....
for(int i = 0; i < vec.size(); ++i)
....
Isso fará com que o compilador aumente o aviso de que o uso misto de variáveis assinadas / não assinadas. se eu fizer a variável index como for( size_t i = 0; i < vec.size(); i++ )
, (ou uma unsigned int
), ela resolverá os problemas.
Quando se torna mais específico o uso de tipos de janelas, a maioria das APIs do Windows trata do DWORD (que é digitado como não assinado por muito tempo).
Portanto, quando eu usar iterações semelhantes, causarei novamente o mesmo aviso. Agora, se eu reescrevê-lo como
DWORD dwCount;
....
for(DWORD i = 0; i < dwCount; ++i)
....
Acho isso um pouco estranho. Pode ser o problema com as percepções.
Concordo que devemos usar o mesmo tipo de variável de índice para evitar que problemas de intervalo possam ocorrer com as variáveis de índice. Por exemplo, se estamos usando
_int64 i64Count; //
....
for(_int64 i = 0; i < i64Count; ++i)
....
Mas no caso de DWORD, ou números inteiros não assinados, há algum problema em reescrevê-lo como
for(int i = 0; (size_t)i < vec.size(); ++i)
Como a maioria das pessoas está trabalhando com problemas semelhantes?
std::size_t
é uma classificação mais alta que a int (ou até longa). Se o tamanho do vetor excederstd::numeric_limits<int>::max()
, você se arrependerá de ter usado int.Respostas:
O vetor possui um typedef que informa o tipo correto a ser usado: -
É quase sempre definido como size_t, mas você não pode confiar nisso
fonte
auto i = 0
? Isso não ajuda em nada,i
tornar-se umint
.using index_t = std::vector<int>::size_type;
.Use um iterador para isso, não um
for
loop.Para os outros, desde que o tipo de variável seja do mesmo tamanho,
static_cast
deve funcionar bem (isto é,DWORD
paraint16_t
)fonte
for (std::vector<int>::iterator i = vec.begin(); i != vec.end(); ++i)
é uma dor de escrever. Terfor (auto i = vec.begin();...
é muito mais legível. Claro,foreach
também está em C ++ 11.O caso que você descreveu também é uma das coisas que eu não gosto em C ++. Mas eu aprendi a conviver com isso, usando
for( size_t i = 0; i < vec.size(); i++ )
ou
for( int i = 0; i < (int)vec.size(); i++ )
(é claro, o último apenas quando não há risco de obter algum transbordamento int).
fonte
O motivo pelo qual o alerta sobre a comparação entre assinado e não assinado é porque o valor assinado provavelmente será convertido em não assinado, o que pode não ser o que você espera.
No seu exemplo (comparando
int
asize_t
),int
será implicitamente convertido emsize_t
(a menos que deint
alguma forma tenha um intervalo maior quesize_t
). Portanto, se o valorint
for negativo, provavelmente será maior que o valor com o qual você o está comparando devido à envolvente. Isso não será um problema se seu índice nunca for negativo, mas você ainda receberá esse aviso.Em vez disso, use um tipo não assinado (como
unsigned int
,size_t
ou, como John B recomenda ,std::vector<int>::size_type
) para a sua variável de índice:Tenha cuidado ao fazer uma contagem regressiva, no entanto:
O acima não funcionará porque
i >= 0
sempre é verdadeiro quandoi
não está assinado. Em vez disso, use o " operador de seta " para loops que fazem contagem regressiva:Como outras respostas apontam, você normalmente deseja usar um iterador para percorrer a
vector
. Aqui está a sintaxe do C ++ 11:fonte
unsigned int
não seja grande o suficiente para manter o tamanho.Uma nova opção para o C ++ 11, você pode fazer coisas como as seguintes
for(decltype(vec.size()) i = 0; i < vec.size(); ++i) {...}
e
for(decltype(dWord) i = 0; i < dWord; ++i) {...}
Embora ele repita um pouco mais do que o loop for básico, não é tão longo quanto as formas pré-11 de especificar valores, e usar esse padrão consistentemente funcionará para a maioria dos termos possíveis, se não todos. deseja comparar, o que o torna ótimo para refatoração de código. Até funciona para casos simples como este:
int x = 3; int final = 32; for(decltype(final) i = x; i < final; ++i)
Além disso, embora você deva usar
auto
sempre que estiver definindoi
algum valor inteligente (comovec.begin()
),decltype
funciona quando estiver definindo uma constante como zero, onde auto resolveria isso apenasint
porque 0 é um literal inteiro simples.Para ser sincero, eu gostaria de ver um mecanismo de compilador para estender a
auto
determinação de tipo para incrementadores de loop para observar o valor que está sendo comparado.fonte
Eu uso um elenco para int, como em
for (int i = 0; i < (int)v.size(); ++i)
. Sim, é feio. Eu culpo o design estúpido da biblioteca padrão, onde eles decidiram usar números inteiros não assinados para representar tamanhos. (Para .. o quê? Estender o intervalo em um bit?)fonte
if(v.size()-1 > 0) { ... }
retornar true para um contêiner vazio? O problema é que os tamanhos também são frequentemente usados em aritmética, esp. com contêineres baseados em índices, que estão solicitando problemas, pois não estão assinados. Basicamente, o uso de tipos não assinados para qualquer coisa além de 1) manipulações bit a bit ou 2) aritmética modular está causando problemas.if(v.size() > 1) { ... }
já que isso torna a intenção mais clara e, como um bônus adicional, a questão de assinado / não assinado se torna nula), vejo como, em alguns casos específicos a assinatura pode ser útil. Eu estou corrigido.