¿Hay alguna diferencia en ++i
y i++
en un for
bucle? ¿Es simplemente una cosa de sintaxis?
¿Hay alguna diferencia en ++i
y i++
en un for
bucle? ¿Es simplemente una cosa de sintaxis?
Respuestas:
a ++ se conoce como postfix.
agregue 1 a a, devuelve el valor anterior.
++ a se conoce como prefijo.
agregue 1 a a, devuelve el nuevo valor.
C#:
string[] items = {"a","b","c","d"};
int i = 0;
foreach (string item in items)
{
Console.WriteLine(++i);
}
Console.WriteLine("");
i = 0;
foreach (string item in items)
{
Console.WriteLine(i++);
}
Salida:
1
2
3
4
0
1
2
3
foreach
y los while
bucles dependen del tipo de incremento que use. Con los bucles for como a continuación, no hay diferencia ya que no está utilizando el valor de retorno de i:
for (int i = 0; i < 5; i++) { Console.Write(i);}
Console.WriteLine("");
for (int i = 0; i < 5; ++i) { Console.Write(i); }
0 1 2 3 4
0 1 2 3 4
Si se utiliza el valor evaluado, el tipo de incremento se vuelve significativo:
int n = 0;
for (int i = 0; n < 5; n = i++) { }
Pre-incremento ++ i incrementa el valor de i y evalúa el nuevo valor incrementado.
int i = 3;
int preIncrementResult = ++i;
Assert( preIncrementResult == 4 );
Assert( i == 4 );
Post-incremento i ++ incrementa el valor de i y evalúa el valor original no incrementado.
int i = 3;
int postIncrementResult = i++;
Assert( postIncrementtResult == 3 );
Assert( i == 4 );
En C ++, generalmente se prefiere el preincremento donde puede usar cualquiera.
Esto se debe a que si usa el incremento posterior, puede requerir que el compilador tenga que generar código que cree una variable temporal adicional. Esto se debe a que tanto los valores anteriores como los nuevos de la variable que se incrementa deben mantenerse en algún lugar porque pueden ser necesarios en otro lugar de la expresión que se está evaluando.
Entonces, al menos en C ++, puede haber una diferencia de rendimiento que guíe su elección de cuál usar.
Esto es principalmente solo un problema cuando la variable que se incrementa es un tipo definido por el usuario con un operador ++ anulado. Para los tipos primitivos (int, etc.) no hay diferencia de rendimiento. Pero vale la pena apegarse al operador anterior al incremento como guía a menos que el operador posterior al incremento sea definitivamente lo que se requiere.
Aquí hay más discusión:
https://web.archive.org/web/20170405054235/http://en.allexperts.com/q/C-1040/Increment-operators.htm
En C ++ si está usando STL, entonces puede estar usando bucles con iteradores. Estos tienen principalmente operadores anulados ++, por lo que es una buena idea atenerse al pre-incremento. Sin embargo, los compiladores se vuelven más inteligentes todo el tiempo, y los más nuevos pueden realizar optimizaciones que significan que no hay diferencia de rendimiento, especialmente si el tipo que se incrementa se define en línea en el archivo de encabezado (como lo son a menudo las implementaciones de STL) para que el compilador pueda ver cómo el método se implementa y luego puede saber qué optimizaciones son seguras de realizar. Aun así, probablemente valga la pena seguir con el pre-incremento porque los bucles se ejecutan muchas veces y esto significa que una pequeña penalización de rendimiento pronto podría amplificarse.
En otros lenguajes como C #, donde el operador ++ no se puede sobrecargar, no hay diferencia de rendimiento. Utilizado en un bucle para avanzar la variable del bucle, los operadores de incremento previo y posterior son equivalentes.
Corrección: se permite la sobrecarga de ++ en C #. Sin embargo, parece que, en comparación con C ++, en C # no puede sobrecargar las versiones pre y post de forma independiente. Por lo tanto, supongo que si el resultado de llamar a ++ en C # no se asigna a una variable o no se usa como parte de una expresión compleja, el compilador reduciría las versiones anteriores y posteriores de ++ a un código que funcione de manera equivalente.
En C # no hay diferencia cuando se usa en un bucle for .
for (int i = 0; i < 10; i++) { Console.WriteLine(i); }
produce lo mismo que
for (int i = 0; i < 10; ++i) { Console.WriteLine(i); }
Como otros han señalado, cuando se usa en general i ++ y ++ tengo una diferencia sutil pero significativa:
int i = 0;
Console.WriteLine(i++); // Prints 0
int j = 0;
Console.WriteLine(++j); // Prints 1
i ++ lee el valor de i y luego lo incrementa.
++ i incrementa el valor de i y luego lo lee.
++i
y i++
realizan las mismas operaciones en el mismo orden: crear una copia temporal de i
; incremente el valor temporal para producir un nuevo valor (no para anular la temperatura); almacenar el nuevo valor en i
; ahora si es ++i
el resultado devuelto es el nuevo valor; si es i++
el resultado devuelto es la copia temporal. Respuesta más detallada aquí: stackoverflow.com/a/3346729/3330348
La pregunta es:
¿Hay alguna diferencia en ++ i e i ++ en un bucle for?
La respuesta es: no .
¿Por qué todas y cada una de las respuestas tienen que entrar en explicaciones detalladas sobre el incremento previo y posterior cuando esto ni siquiera se pregunta?
Este bucle for:
for (int i = 0; // Initialization
i < 5; // Condition
i++) // Increment
{
Output(i);
}
Se traduciría a este código sin usar bucles:
int i = 0; // Initialization
loopStart:
if (i < 5) // Condition
{
Output(i);
i++ or ++i; // Increment
goto loopStart;
}
¿Ahora importa si pones i++
o ++i
como incremento aquí? No, no lo hace, ya que el valor de retorno de la operación de incremento es insignificante. i
se incrementará DESPUÉS de la ejecución del código que está dentro del cuerpo del bucle for.
Como preguntas sobre la diferencia en un bucle, supongo que te refieres
for(int i=0; i<10; i++)
...;
En ese caso, no tiene diferencia en la mayoría de los idiomas: el bucle se comporta igual independientemente de si escribe i++
y ++i
. En C ++, puede escribir sus propias versiones de los operadores ++, y puede definir significados separados para ellos, si eli
es de un tipo definido por el usuario (su propia clase, por ejemplo).
La razón por la que no importa más arriba es porque no utiliza el valor de i++
. Otra cosa es cuando lo haces
for(int i=0, a = 0; i<10; a = i++)
...;
Ahora bien, no es una diferencia, porque como otros señalan, i++
medios de incremento, pero se evalúan como el valor anterior , pero ++i
los medios de incremento, pero a evaluari
(por lo que se evaluará al nuevo valor). En el caso anterior, a
se le asigna el valor anterior de i, mientras que i se incrementa.
Como muestra este código (vea el MSIL desmontado en los comentarios), el compilador C # 3 no hace distinción entre i ++ y ++ i en un bucle for. Si se tomara el valor de i ++ o ++, definitivamente habría una diferencia (esto se compiló en Visutal Studio 2008 / Release Build):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace PreOrPostIncrement
{
class Program
{
static int SomethingToIncrement;
static void Main(string[] args)
{
PreIncrement(1000);
PostIncrement(1000);
Console.WriteLine("SomethingToIncrement={0}", SomethingToIncrement);
}
static void PreIncrement(int count)
{
/*
.method private hidebysig static void PreIncrement(int32 count) cil managed
{
// Code size 25 (0x19)
.maxstack 2
.locals init ([0] int32 i)
IL_0000: ldc.i4.0
IL_0001: stloc.0
IL_0002: br.s IL_0014
IL_0004: ldsfld int32 PreOrPostIncrement.Program::SomethingToIncrement
IL_0009: ldc.i4.1
IL_000a: add
IL_000b: stsfld int32 PreOrPostIncrement.Program::SomethingToIncrement
IL_0010: ldloc.0
IL_0011: ldc.i4.1
IL_0012: add
IL_0013: stloc.0
IL_0014: ldloc.0
IL_0015: ldarg.0
IL_0016: blt.s IL_0004
IL_0018: ret
} // end of method Program::PreIncrement
*/
for (int i = 0; i < count; ++i)
{
++SomethingToIncrement;
}
}
static void PostIncrement(int count)
{
/*
.method private hidebysig static void PostIncrement(int32 count) cil managed
{
// Code size 25 (0x19)
.maxstack 2
.locals init ([0] int32 i)
IL_0000: ldc.i4.0
IL_0001: stloc.0
IL_0002: br.s IL_0014
IL_0004: ldsfld int32 PreOrPostIncrement.Program::SomethingToIncrement
IL_0009: ldc.i4.1
IL_000a: add
IL_000b: stsfld int32 PreOrPostIncrement.Program::SomethingToIncrement
IL_0010: ldloc.0
IL_0011: ldc.i4.1
IL_0012: add
IL_0013: stloc.0
IL_0014: ldloc.0
IL_0015: ldarg.0
IL_0016: blt.s IL_0004
IL_0018: ret
} // end of method Program::PostIncrement
*/
for (int i = 0; i < count; i++)
{
SomethingToIncrement++;
}
}
}
}
Uno (++ i) es preincremento, uno (i ++) es postincremento. La diferencia está en qué valor se devuelve inmediatamente de la expresión.
// Psuedocode
int i = 0;
print i++; // Prints 0
print i; // Prints 1
int j = 0;
print ++j; // Prints 1
print j; // Prints 1
Editar: Woops, ignoró por completo el lado del bucle de las cosas. No hay una diferencia real en los bucles for cuando es la parte de 'paso' (para (...; ...;)), pero puede entrar en juego en otros casos.
No hay diferencia si no está utilizando el valor después del incremento en el bucle.
for (int i = 0; i < 4; ++i){
cout<<i;
}
for (int i = 0; i < 4; i++){
cout<<i;
}
Ambos bucles imprimirán 0123.
Pero la diferencia viene cuando usa el valor después del incremento / decremento en su ciclo de la siguiente manera:
Bucle Pre Incremento:
for (int i = 0,k=0; i < 4; k=++i){
cout<<i<<" ";
cout<<k<<" ";
}
Salida: 0 0 1 1 2 2 3 3
Post Increment Loop:
for (int i = 0, k=0; i < 4; k=i++){
cout<<i<<" ";
cout<<k<<" ";
}
Salida: 0 0 1 0 2 1 3 2
Espero que la diferencia sea clara al comparar la salida. El punto a tener en cuenta aquí es que el incremento / decremento siempre se realiza al final del ciclo for y, por lo tanto, los resultados se pueden explicar.
Aquí hay una muestra de Java y el código de byte, post- y preIncrement no muestran diferencias en Bytecode:
public class PreOrPostIncrement {
static int somethingToIncrement = 0;
public static void main(String[] args) {
final int rounds = 1000;
postIncrement(rounds);
preIncrement(rounds);
}
private static void postIncrement(final int rounds) {
for (int i = 0; i < rounds; i++) {
somethingToIncrement++;
}
}
private static void preIncrement(final int rounds) {
for (int i = 0; i < rounds; ++i) {
++somethingToIncrement;
}
}
}
Y ahora para el código de bytes (javap -private -c PreOrPostIncrement):
public class PreOrPostIncrement extends java.lang.Object{
static int somethingToIncrement;
static {};
Code:
0: iconst_0
1: putstatic #10; //Field somethingToIncrement:I
4: return
public PreOrPostIncrement();
Code:
0: aload_0
1: invokespecial #15; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: sipush 1000
3: istore_1
4: sipush 1000
7: invokestatic #21; //Method postIncrement:(I)V
10: sipush 1000
13: invokestatic #25; //Method preIncrement:(I)V
16: return
private static void postIncrement(int);
Code:
0: iconst_0
1: istore_1
2: goto 16
5: getstatic #10; //Field somethingToIncrement:I
8: iconst_1
9: iadd
10: putstatic #10; //Field somethingToIncrement:I
13: iinc 1, 1
16: iload_1
17: iload_0
18: if_icmplt 5
21: return
private static void preIncrement(int);
Code:
0: iconst_0
1: istore_1
2: goto 16
5: getstatic #10; //Field somethingToIncrement:I
8: iconst_1
9: iadd
10: putstatic #10; //Field somethingToIncrement:I
13: iinc 1, 1
16: iload_1
17: iload_0
18: if_icmplt 5
21: return
}
Sí hay. La diferencia está en el valor de retorno. El valor de retorno de "++ i" será el valor después de incrementar i. El retorno de "i ++" será el valor antes de incrementar. Esto significa ese código que se parece a lo siguiente:
int a = 0;
int b = ++a; // a is incremented and the result after incrementing is saved to b.
int c = a++; // a is incremented again and the result before incremening is saved to c.
Por lo tanto, a sería 2, y byc serían cada uno 1.
Podría reescribir el código así:
int a = 0;
// ++a;
a = a + 1; // incrementing first.
b = a; // setting second.
// a++;
c = a; // setting first.
a = a + 1; // incrementing second.
No hay diferencia real en ambos casos ' i
' se incrementará en 1.
Pero hay una diferencia cuando lo usa en una expresión, por ejemplo:
int i = 1;
int a = ++i;
// i is incremented by one and then assigned to a.
// Both i and a are now 2.
int b = i++;
// i is assigned to b and then incremented by one.
// b is now 2, and i is now 3
Hay más en ++ i e i ++ que los bucles y las diferencias de rendimiento. ++ i devuelve un valor l e i ++ devuelve un valor r. En base a esto, hay muchas cosas que puede hacer para (++ i) pero no para (i ++).
1- It is illegal to take the address of post increment result. Compiler won't even allow you.
2- Only constant references to post increment can exist, i.e., of the form const T&.
3- You cannot apply another post increment or decrement to the result of i++, i.e., there is no such thing as I++++. This would be parsed as ( i ++ ) ++ which is illegal.
4- When overloading pre-/post-increment and decrement operators, programmers are encouraged to define post- increment/decrement operators like:
T& operator ++ ( )
{
// logical increment
return *this;
}
const T operator ++ ( int )
{
T temp( *this );
++*this;
return temp;
}
Me desconcierta por qué las personas pueden escribir la expresión de incremento en for-loop como i ++.
En un ciclo for, cuando el tercer componente es una declaración de incremento simple, como en
for (i=0; i<x; i++)
o
for (i=0; i<x; ++i)
No hay diferencia en las ejecuciones resultantes.
Como dice @Jon B , no hay diferencia en un bucle for.
Pero en un bucle while
o do...while
, podría encontrar algunas diferencias si está haciendo una comparación con el ++i
oi++
while(i++ < 10) { ... } //compare then increment
while(++i < 10) { ... } //increment then compare
En javascript debido a lo siguiente, i ++ puede ser mejor para usar:
var i=1;
alert(i++); // before, 1. current, 1. after, 2.
alert(i); // before, 2. current, 2. after, 2.
alert(++i); // before, 2. current, 3 after, 3.
Mientras que las matrices (creo que todas) y algunas otras funciones y llamadas usan 0 como punto de partida, tendría que establecer i en -1 para que el bucle funcione con la matriz cuando se usa ++ i .
Al usar i ++, el siguiente valor usará el valor aumentado. Podrías decir que i ++ es la forma en que los humanos cuentan, porque puedes comenzar con un 0 .
Para entender lo que hace un bucle FOR
La imagen de arriba muestra que FOR se puede convertir a WHILE , ya que finalmente tienen el mismo código de ensamblaje (al menos en gcc). Entonces podemos dividir FOR en un par de piezas, para comprender lo que hace.
for (i = 0; i < 5; ++i) {
DoSomethingA();
DoSomethingB();
}
es igual a la versión MIENTRAS
i = 0; //first argument (a statement) of for
while (i < 5 /*second argument (a condition) of for*/) {
DoSomethingA();
DoSomethingB();
++i; //third argument (another statement) of for
}
Significa que puede usar FOR como una versión simple de WHILE :
El primer argumento de FOR (int i) se ejecuta, fuera, antes del bucle.
El tercer argumento de FOR (i ++ o ++ i) se ejecuta, dentro, en la última línea del bucle.
TL: DR: no importa si
i++
o++i
, sabemos que cuando son independientes, no hacen diferencia sino +1 en sí mismos.En la escuela, generalmente enseñan la forma i ++, pero también hay muchas personas que prefieren la forma ++ i debido a varias razones .
NOTA: En el pasado, i ++ tiene muy poco impacto en el rendimiento, ya que no solo suma uno por sí mismo, sino que también mantiene el valor original en el registro. Pero por ahora, no hace ninguna diferencia, ya que el compilador hace que la parte plus sea igual.
Puede haber una diferencia para los bucles. Esta es la aplicación práctica de post / pre-incremento.
int i = 0;
while(i++ <= 10) {
Console.Write(i);
}
Console.Write(System.Environment.NewLine);
i = 0;
while(++i <= 10) {
Console.Write(i);
}
Console.ReadLine();
Mientras que el primero cuenta hasta 11 y se repite 11 veces, el segundo no.
Principalmente, esto se usa bastante en un tiempo simple (x--> 0); - - Bucle para iterar, por ejemplo, todos los elementos de una matriz (exceptuando las construcciones foreach aquí).
Ambos incrementan el número. ++i
es equivalente a i = i + 1
.
i++
y ++i
son muy similares pero no exactamente iguales. Ambos incrementan el número, pero ++i
incrementan el número antes de que se evalúe la expresión actual, mientras que i++
incrementa el número después de que se evalúa la expresión.
int i = 3;
int a = i++; // a = 3, i = 4
int b = ++a; // b = 4, a =
Mira este enlace .
Sí, hay una diferencia entre ++i
y i++
en un for
bucle, aunque en casos de uso inusuales; cuando se usa una variable de bucle con operador de incremento / decremento en el bloque for o dentro de la expresión de prueba de bucle , o con una de las variables de bucle . No, no es simplemente una cuestión de sintaxis.
Como i
en un código significa evaluar la expresión i
y el operador no significa una evaluación sino solo una operación;
++i
significa incrementar el valor i
en 1 y luego evaluar i
,i++
significa evaluar i
y luego incrementar el valor i
en 1.Entonces, lo que se obtiene de cada dos expresiones difiere porque lo que se evalúa difiere en cada una. Todo lo mismo para --i
yi--
Por ejemplo;
let i = 0
i++ // evaluates to value of i, means evaluates to 0, later increments i by 1, i is now 1
0
i
1
++i // increments i by 1, i is now 2, later evaluates to value of i, means evaluates to 2
2
i
2
En casos de uso inusual, sin embargo, el siguiente ejemplo suena útil o no importa, muestra una diferencia
for(i=0, j=i; i<10; j=++i){
console.log(j, i)
}
for(i=0, j=i; i<10; j=i++){
console.log(j, i)
}
Para i
los tipos definidos por el usuario, estos operadores podrían (pero no deberían ) tener semánticas significativamente diferentes en el contexto de un índice de bucle, y esto podría (pero no debería) afectar el comportamiento del bucle descrito.
Además, en c++
general es más seguro usar el formulario de pre-incremento ( ++i
) porque se optimiza más fácilmente. (Scott Langham me ganó en este bocado . Maldito seas, Scott)
No sé para los demás idiomas, pero en Java ++ i es un prefijo de la subasta , que significa: incrementar i en 1 y luego usar el nuevo valor de i en la expresión en la que i reside, y i ++ es un incremento de sufijo que significa lo siguiente : use el valor actual de i en la expresión y luego aumente en 1. Ejemplo:
public static void main(String [] args){
int a = 3;
int b = 5;
System.out.println(++a);
System.out.println(b++);
System.out.println(b);
} y el resultado es:
i ++; ++ i; ambos son similares ya que no se usan en una expresión.
class A {
public static void main (String []args) {
int j = 0 ;
int k = 0 ;
++j;
k++;
System.out.println(k+" "+j);
}}
prints out : 1 1