post-increment - mismo - i++ es igual a++ i
Diferencia entre i++ y++ i en un bucle? (21)
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
incrementa 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 =
Revisa este enlace .
¿Hay una diferencia en ++i
y i++
en un bucle for
? ¿Es simplemente una cosa de sintaxis?
Aquí hay una muestra de Java y el Byte-Code, 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
}
Como dice @Jon B , no hay diferencia en un bucle for.
Pero en un while
o en do...while
bucle, puede encontrar algunas diferencias si está haciendo una comparación con el ++i
o i++
while(i++ < 10) { ... } //compare then increment
while(++i < 10) { ... } //increment then compare
Como se muestra en este código (ver el MSIL descompuesto 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 ++ i, 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++;
}
}
}
}
En c # no hay diferencia cuando se usa en un bucle for .
for (int i = 0; i < 10; i++) { Console.WriteLine(i); }
salidas lo mismo que
for (int i = 0; i < 10; ++i) { Console.WriteLine(i); }
Como han señalado otros, cuando se usan 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.
En javascript debido al siguiente i ++ puede ser mejor 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 configurar i en -1 para que el bucle funcione con la matriz cuando se usa ++ i .
Cuando se utiliza i ++, el siguiente valor utilizará el valor aumentado. Se podría decir que i ++ es la forma en que los humanos cuentan, porque puedes comenzar con un 0 .
Hay más para ++ 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;
}
La pregunta es:
¿Hay una diferencia en ++ i y i ++ en un bucle for?
La respuesta es: no .
¿Por qué todas y cada una de las otras respuestas tienen que ir en explicaciones detalladas acerca de los incrementos previos y posteriores cuando esto ni siquiera se pregunta?
Este for-loop:
for (int i = 0; // Initialization
i < 5; // Condition
i++) // Increment
{
Output(i);
}
Se traduciría a este código sin utilizar 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. Se incrementará DESPUÉS de la ejecución del código que está dentro del cuerpo del bucle for.
Me sorprende que la gente escriba la expresión de incremento en for-loop como i ++.
En un bucle for, cuando el tercer componente es una instrucció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.
No hay diferencia real en ambos casos '' i
'' se incrementará en 1.
Pero hay una diferencia cuando lo usas 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
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 se produce cuando utiliza el valor después del incremento / decremento en su bucle como se muestra a continuación:
Pre Incremento Bucle:
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, se pueden explicar los resultados.
No sé para los otros lenguajes, pero en Java ++ i es un incremento de prefijo que significa: aumente i en 1 y luego use el nuevo valor de i en la expresión en la que reside i , e i ++ es un incremento de postfix que significa lo siguiente : use el valor actual de i en la expresión y luego auméntelo 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 la salida es:
- 4
- 5
- 6
Para i
de tipos definidos por el usuario, estos operadores podrían (pero no deberían ) tener semáticas 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++
es generalmente más seguro utilizar el formulario de preincremento ( ++i
) porque se optimiza más fácilmente. (Scott Langham me golpeó a este tidbit . Maldito seas, Scott)
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 más bien en un simple tiempo (x--> 0); - - Bucle para iterar, por ejemplo, todos los elementos de una matriz (eximiendo foreach-constructs aquí).
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 que el código 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 b y c 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.
Sí, hay una diferencia entre ++i
y i++
en un bucle for
, aunque en casos de uso inusuales; cuando se utiliza 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 cosa 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 el valor de incremento dei
por 1 y luego evalúoi
, -
i++
significa evaluari
y luego incrementar el valor dei
en 1.
Entonces, lo que se obtiene de cada dos expresiones difiere porque lo que se evalúa difiere en cada una. Todo igual para --i
y i--
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 inusuales, sin embargo el siguiente ejemplo suena útil o no, 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)
}
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
Edición: Woops, ignoró por completo el lado del bucle de las cosas. No hay una diferencia real en los bucles for cuando se trata de la parte ''step'' (para (...; ...;)), pero puede entrar en juego en otros casos.
Ya que preguntas por la diferencia en un bucle, supongo que te refieres a
for(int i=0; i<10; i++)
...;
En ese caso, no tiene ninguna diferencia en la mayoría de los idiomas: el bucle se comporta de la misma manera, 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 la i
es de un tipo definido por el usuario (su propia clase, por ejemplo).
La razón por la que no importa arriba es porque no usas el valor de i++
. Otra cosa es cuando lo haces.
for(int i=0, a = 0; i<10; a = i++)
...;
Ahora, hay una diferencia, porque como lo señalan otros, i++
significa incremento, pero evalúa al valor anterior , pero ++i
significa incremento, pero evalúa a i
(por lo tanto, evaluaría al nuevo valor). En el caso anterior, a
se asigna el valor anterior de i, mientras que i se incrementa.
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
Pre-incremento ++ i incrementa el valor de i y se evalúa al nuevo valor incrementado.
int i = 3;
int preIncrementResult = ++i;
Assert( preIncrementResult == 4 );
Assert( i == 4 );
I ++ post-incremento incrementa el valor de i y se evalúa al valor original no incrementado.
int i = 3;
int postIncrementResult = i++;
Assert( postIncrementtResult == 3 );
Assert( i == 4 );
En C ++, el pre-incremento generalmente se prefiere donde se puede usar cualquiera de los dos.
Esto se debe a que si usa el incremento posterior, puede requerir que el compilador tenga que generar un 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 está incrementando deben mantenerse en algún lugar porque pueden ser necesarios en otra parte de la expresión que se evalúa.
Por lo tanto, 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 ceñirse al operador de pre-incremento como una guía a menos que el operador de post-incremento sea definitivamente lo que se requiere.
Hay un poco más de discusión aquí:
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 atenerse al pre-incremento es una buena idea. 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 suelen ser las implementaciones de STL) para que el compilador pueda ver cómo el método se implementa y luego se puede saber qué optimizaciones son seguras de realizar. Aun así, es probable que todavía valga la pena mantener el pre-incremento porque los bucles se ejecutan muchas veces y esto significa que una pequeña penalización en el rendimiento podría amplificarse pronto.
En otros idiomas, como C #, donde el operador ++ no se puede sobrecargar, no hay diferencia de rendimiento. Usados en un bucle para avanzar la variable de bucle, los operadores de incremento pre y post son equivalentes.
Corrección: se permite la sobrecarga ++ en C #. Sin embargo, parece que en comparación con C ++, en c # no puede sobrecargar las versiones pre y post independientemente. Por lo tanto, supongo que si el resultado de la llamada ++ en C # no se asigna a una variable o se utiliza como parte de una expresión compleja, el compilador reducirá las versiones anteriores y posteriores de ++ al código que se desempeña de manera equivalente.
a ++ se conoce como postfix.
Añadir 1 a un, devuelve el valor anterior.
++ a se conoce como prefijo.
agregar 1 a un, devuelve el nuevo valor.
DO#:
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
bucles foreach
y while dependen del tipo de incremento que utilice. Con los bucles for como abajo, no hay diferencia, ya que no estás usando 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 usa el valor como evaluado, entonces el tipo de incremento se vuelve significativo:
int n = 0;
for (int i = 0; n < 5; n = i++) { }