2010-02-12 34 views
8

No he usado C++ por un tiempo. He estado dependiendo de mi compilador de Java para hacer la optimización.C++ Declarando int en el ciclo for

¿Cuál es la forma más optimizada de hacer un ciclo for en C++? ¿O todo es lo mismo ahora con compiladores modernos? En los "viejos tiempos" había una diferencia.

for (int i=1; i<=100; i++) 

O

int i; 
for (i=1; i<=100; i++) 

O

int i = 1; 
for (; i<=100; i++) 

¿Es lo mismo en C?

EDIT: bien, por lo que el consenso abrumador es utilizar el primer caso y dejar que el compilador optimizar con ello si se quiere.

+6

Este tipo de pregunta es realmente una mala señal ... –

+0

+1 Por preguntar esto, para que el mito pueda ser debuffed – Andres

Respuesta

12

Diría que el compilador probablemente optimiza cosas triviales como esta, y no debe preocuparse por ellas. La primera opción es la más legible, por lo que debes usarla.

EDITAR: Agregando lo que dijeron otras respuestas, también existe la diferencia de que si declara la variable en el inicializador de bucle, dejará de existir después de que termine el ciclo.

+2

En cuanto a su edición, esto depende del compilador. He visto al menos un compilador (MSVC++ 6.0) donde la variable no deja de existir después de que termina el ciclo. –

+2

@Jeff Los compiladores que cumplen con los estándares restringirán el alcance de _i_ el ciclo for, pero existen compiladores más antiguos, como MSVC++ 6.0, que no lo hacen. Por lo tanto, si está utilizando un compilador anterior, es algo de lo que debe tener cuidado. De acuerdo con el estándar de idioma, sin embargo, el alcance está restringido al ciclo for. Los compiladores recientes deberían comportarse correctamente en ese sentido. –

+0

En MSVC, el truco "#define para if (0) {} else for" podría usarse para obtener el comportamiento correcto. Ah sí, los buenos viejos tiempos ... –

4

Es lo mismo. El compilador optimizará estos para lo mismo.

Incluso si no fueran iguales, la diferencia en comparación con el cuerpo real de su bucle sería insignificante. No debe preocuparse por micro-optimizaciones como esta. Y no debe hacer micro-optimizaciones a menos que esté evaluando el rendimiento para ver si realmente hace la diferencia.

3

Pasa lo mismo en términos de velocidad. El compilador optimizará si no tiene un uso posterior de i.

En términos de estilo, pondría la definición en la construcción del lazo, ya que reduce el riesgo de conflicto si define otro yo más tarde.

9

La diferencia es el alcance.

for(int i = 1; i <= 100; ++i) 

generalmente es preferible porque entonces el alcance de i se limita a la de bucle. Si lo declaras antes del ciclo for, entonces continúa existiendo después de que el ciclo for haya terminado y pueda entrar en conflicto con otras variables. Si solo lo está usando en el ciclo for, no hay razón para dejarlo existir por más tiempo.

+0

En algunos de los compiladores más antiguos, el alcance de i, es hasta el final de la función. moviendo el int, fuera del lazo te mantiene bien con otros compiladores. – EvilTeach

+0

@EvilTech Solo compiladores antiguos y no compatibles tendrán ese problema. Entonces, a menos que piense que hay una buena posibilidad de que su código se use con dicho compilador, no me preocuparía. Si es un problema, colocar un par adicional de llaves alrededor del bucle for solucionará el problema. –

1

No se preocupe por las micro-optimizaciones, deje que el compilador lo haga. Elija lo que sea más legible. Tenga en cuenta que al declarar una variable dentro de una declaración de inicialización for, la variable se encuentra en la declaración for (C++ 03 § 6.5.3 1), aunque el comportamiento exacto de los compiladores puede variar (algunos le permiten elegir). Si el código fuera del bucle utiliza la variable, declare fuera del bucle. Si la variable es verdaderamente local para el ciclo, declararlo en el inicializador.

-1

Es todo lo mismo.

1

Ya se ha mencionado que la principal diferencia entre los dos es el alcance.Asegúrese de entender cómo su compilador maneja el alcance de un int declarada como

for (int i = 1; ...;...) 

Sé que cuando se utiliza MSVC++ 6, que todavía está en el ámbito fuera del bucle, tal como si se tratara de declarar antes del bucle . Este comportamiento es diferente de VS2005, y tendría que verificarlo, pero creo que la última versión de gcc que utilicé. En ambos compiladores, esa variable solo estaba dentro del alcance dentro del ciclo.

+0

Es un error bien conocido en VC++ 6. Si realmente te importa rodear el bucle for con otro par de llaves. – jmucchiello

5

Digamos que el póster original tenía un bucle que realmente querían optimizar, cada instrucción contada. ¿Cómo podemos descubrir, empíricamente, la respuesta a su pregunta?

gcc al menos tiene un interruptor útil, aunque poco común, '-S'. Vacia la versión de código ensamblador del archivo .c y se puede usar para responder preguntas como OP plantea. Escribí un programa simple:

int main() 
{ 
    int sum = 0; 

    for(int i=1;i<=10;++i) 
    { 
     sum = sum + i; 
    } 
    return sum; 
} 

y corrió: gcc -O0 -std=c99 -S main.c, la creación de la versión de montaje del programa principal. He aquí el contenido de main.s (con algunos de la pelusa eliminado):

movl $0, -8(%rbp) 
    movl $1, -4(%rbp) 
    jmp  .L2 
.L3: 
    movl -4(%rbp), %eax 
    addl %eax, -8(%rbp) 
    addl $1, -4(%rbp) 
.L2: 
    cmpl $10, -4(%rbp) 
    jle  .L3 

Usted no necesita ser un experto ensamblaje de averiguar lo que está pasando. movl mueve valores, addl agrega cosas, cmpl se compara y jle significa 'jump if less than', $ es para constantes. Está cargando 0 en algo - eso debe ser 'suma', 1 en otra cosa - ¡ah, 'yo'! Un salto a L2 donde hacemos la comparación de 10, salta a L3 para hacer el complemento. Llega a L2 para la comparación de nuevo. ¡Ordenado! A para bucle.

cambiar el programa a:

int main() 
{ 
    int sum = 0; 
    int i=1; 
    for(;i<=10;++i) 
    { 
     sum = sum + i; 
    } 
    return sum; 
} 

Vuelva a ejecutar gcc y el conjunto resultante será muy similar. Hay algunas cosas pasando con la grabación de números de línea, por lo que no serán idénticos, pero el conjunto termina siendo el mismo. Mismo resultado con el último caso. Entonces, incluso sin optimización, el código es casi el mismo.

Para divertirse, vuelva a ejecutar gcc con '-O3' en lugar de '-O0' para permitir la optimización y ver el archivo .s.

main: 
movl $55, %eax 
ret 

gcc no sólo descubrió que estábamos haciendo un bucle, pero también se dio cuenta de que iba a ser ejecutar un número constante de veces que lo hizo el lazo para nosotros en tiempo de compilación, tiraron a cabo 'i' y la 'suma' y codificó la respuesta con fuerza - 55! Eso es RÁPIDO, aunque un poco artificial.

¿Moral de la historia? Dedique su tiempo a garantizar que su código esté limpio y bien diseñado. Código de legibilidad y mantenimiento. Los muchachos que viven del rocío de las montañas y los cheetos son mucho más listos que nosotros y se han encargado de la mayoría de estos simples problemas de optimización para nosotros. ¡Que te diviertas!

1
for(int i = 1; i <= 100; ++i) 

Esto es más fácil de leer, excepto ANSI C/C89 donde no es válido.

Cuestiones relacionadas