2011-11-02 8 views
7
#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

El error te dice exactamente qué es lo que está mal. Hay exactamente una operación de comparación por ciclo for, para que pueda ver qué se compara con qué. Puede ver que 'i' es de un tipo con signo (¡eligió el tipo!), Por lo que lógicamente implica que la otra expresión es de tipo sin signo. –

+0

Posible duplicado de [¿Cómo puedo corregir advertencias como: "comparación entre firmado y sin firmar"?] (Http://stackoverflow.com/questions/859943/how-can-fix-warnings-like-comparison-between- firm-and-unsigned) –

Respuesta

13

¿Por qué hay una advertencia con -Wsign-compare?

Como el nombre de la advertencia y su texto implican, el problema es que está comparando un entero con signo y sin signo. En general se supone que esto es un accidente.

Para evitar esta advertencia, simplemente necesita asegurarse de que ambos operandos de < (o cualquier otro operador de comparación) estén firmados o no firmados.

¿Cómo podría hacerlo mejor?

La forma idiomática de escribir un bucle for es inicializar tanto el contador y el límite en la primera declaración:

for (std::size_t i = 0, max = vec.size(); i != max; ++i) 

Esto ahorra recomputing size() en cada iteración.

También podría (y probablemente debería) utiliza iteradores en lugar de índices:

for (auto it = vec.begin(), end = vec.end(); it != end; ++it) 

auto aquí es una forma abreviada de std::vector<int>::iterator. Los iteradores funcionan para cualquier tipo de contenedor, mientras que los índices lo limitan a C-arrays, deque y vector.

+0

esto funcionó. aunque max() no funcionó, lo cambié a max. gracias – code511788465541441

+0

No utilizaría la forma máxima porque - dependiendo de su ciclo, el tamaño del vec puede cambiar, por lo que es más seguro comprobar siempre el tamaño real del vec. – inf

+0

Inicializar el límite primero solo funciona si el contenedor no cambia de tamaño dentro del bucle. De lo contrario, declararía el límite como una variable 'const' antes del ciclo, para darle al compilador munición adicional contra los programadores que intentan cambiar la variable. –

2

La variable de i es un entero mientras que la función size miembro del vector que devuelve un Allocator::size_type es más probable que devuelve un size_t, que es casi siempre implementado como int sin firmar de algún tamaño.

5

Se debe a que la función .size() de la clase de vectores no es de tipo int, pero de tipo vector :: size_type

uso o que auto i = 0u y los mensajes debe desaparecer.

+0

El uso de auto aquí no funcionará, ya que el tipo deducido se firmaría int. Usando auto i = 0U; trabajos. –

+0

@SR_ Así es, gracias arreglado. – inf

2

Haga su int i como size_type i.
std::vector::size() devolverá size_type que es unsigned int ya que el tamaño no puede ser -ve.
La advertencia es obviamente porque está comparando un entero con signo con un entero sin signo.

2

contestador después de tantas respuestas, pero nadie tomó nota del final del bucle .. Por lo tanto, aquí está mi respuesta completa:

  1. Para eliminar la advertencia, cambiar el tipo del i 's para ser unsigned, auto (por C++ 11), o std::vector<your_type>::size_type
  2. Sus bucles for se SEG-culpa, si se utiliza este índice como i - debe recorrer desde 0 a size-1, ambos inclusive. Por lo tanto, el cambio a ser
    for(std::vector<your_type>::size_type i = 0; i < vector_xxx.size(); ++i)
    (nótese el <, no <=; mi consejo no es para usar con <=.begin() - 1, porque puede tener un vector 0 tamaño y que se tener problemas con eso :)).
  3. Para hacer esto más genérico, ya que estás usando un contenedor y estás iterando a través de él, puedes usar iterator s. Esto facilitará el cambio futuro del tipo de contenedor (si no necesita la posición exacta como número, por supuesto). Por tanto, os escribo de esta manera:

for(std::vector<your_type>::iterator iter = vector_XXX.begin(); 
    iter != vector_XXX.end(); 
    ++iter) 
{ 
    //.. 
} 
2

Recibirá esta advertencia porque el tamaño de un contenedor en C++ es de tipo sin signo y la mezcla de tipos con signo/sin firmar es peligrosa.

Lo que hago normalmente es

for (int i=0,n=v.size(); i<n; i++) 
    .... 

esto es en mi opinión la mejor manera de utilizar los índices porque el uso de un tipo sin signo de un índice (o el tamaño de un contenedor) es un error lógico.

Los tipos sin signo deben usarse solo cuando se preocupa por la representación de bit y cuando se va a usar el comportamiento modulo- (2 ** n) en overflow. El uso de tipos sin firmar solo porque un valor nunca es negativo es una tontería.

Un error típico de la utilización de los tipos sin signo para tamaños o índices es, por ejemplo

// Draw all lines between adjacent points 
for (size_t i=0; i<pts.size()-1; i++) 
    drawLine(pts[i], pts[i+1]); 

el código anterior es UB cuando el conjunto de puntos está vacío porque en C++ 0u-1 con es un número positivo enorme. El motivo por el cual C++ usa un tipo sin signo para el tamaño de contenedores es porque esa opción es un patrimonio histórico de computadoras de 16 bits (y la semántica de C++ con tipos sin signo de IMO era la opción incorrecta incluso en aquel entonces).

3

int está firmado de manera predeterminada; es equivalente a escribir signed int. La razón por la que recibe una advertencia es porque size() devuelve un vector::size_type que es más que probable que no esté firmado.

Esto tiene un peligro potencial ya que signed int y unsigned int tienen diferentes rangos de valores. signed int puede contener valores entre –2147483648 a 2147483647 mientras que un unsigned int puede contener valores entre 0 a 4294967295 (suponiendo que int es de 32 bits).

0

Declarar 'size_t i' para mí funciona bien.

1

por lo general a resolver de esta manera:

for(int i = 0; i <= (int)vector_string.size(); i++) 

que utilizan la conversión de estilo C porque es más corto y más fácil de leer que el C++ static_cast<int>(), y consigue el mismo efecto.

Existe un potencial de desbordamiento aquí, pero solo si su tamaño de vector es mayor que el mayor int, generalmente 2147483647. Nunca en mi vida tuve un vector tan grande. Si hay incluso una posibilidad remota de utilizar un vector más grande, una de las respuestas que sugiere size_type sería más apropiada.

No me preocupo por llamar al size() repetidamente en el bucle, ya que es probable que sea un acceso en línea a una variable miembro que no introduce gastos generales.

Cuestiones relacionadas