c++ - que - preincremento y postincremento
¿Cuál es la diferencia entre los operadores "++" y "+=1"? (10)
En un ciclo en C ++, suelo encontrar situaciones para usar ++
o +=1
, pero no puedo decir la diferencia. Por ejemplo, si tengo un número entero
int num = 0;
y luego en un bucle hago:
num ++;
o
num += 1;
ambos aumentan el valor de num
, pero ¿cuál es su diferencia? Dudo num++
podría funcionar más rápido que num+=1
, pero ¿cómo? ¿Es esta diferencia lo suficientemente sutil para ser ignorada?
++ se usa para incrementar el valor en 1, mientras que usando + = puede incrementarse en otra cantidad.
Algunos de ustedes se están acercando a la diferencia, pero debe establecerse muy claramente:
SON OPERADORES MUY DIFERENTES.
Los operadores preincremento y postincremento están diseñados para usarse DENTRO DE LAS EXPRESIONES para cambiar el valor de la variable ANTES o DESPUÉS de que se use el valor de la variable en cualquier expresión que lo encierre. Cuando se usa el operador postincrement, el valor OLD de la variable se usa para evaluar la expresión adjunta y solo después de eso se incrementa la variable.
Por ejemplo:
i = 10;
j = i++; // This causes j to be 10 while i becomes 11.
Es por eso que se llama el operador postincremento. La variable se incrementa POST (DESPUÉS) su valor se usa en la expresión mayor (aquí una expresión de asignación).
Sin embargo, si lo haces:
i = 10;
j = ++i; // Now both i and j will be 11 because the increment
// of i occurs PRE (BEFORE) its value is used in the greater expression.
Ambos operadores aumentan el valor de n en 1. La diferencia entre ellos existe cuando usa los operadores junto con el operador de asignación.
Por ejemplo:
Primer caso - Operador de incremento de posos
int n=5;
int new_var;
new_var=n++;
print("%d",new_var);
Salida = 5
Segundo caso
int n=5;
n+=1;
new_var=n;
print("%d",new_var);
Salida = 6
Esto es muy similar al resultado del operador de preincremento.
Segundo caso usando el operador de preincremento
int n=5;
new_var=++n;
print("%d",new_var);
Salida = 6
En general, son lo mismo y no tiene importancia aclarar la diferencia entre ellos. Pero la implementación de estas dos afirmaciones es de hecho diferente. Por ejemplo, un + = 1 compilando para asentar es
agregar un, 1
y a ++ o ++ a es
inc a
Puede haber una pequeña diferencia en la eficiencia porque son dos operaciones diferentes de la CPU.
Estos dos operadores pueden parecer similares, pero son bastante diferentes.
Para tipos primitivos (punteros, enteros, etc.) ambos incrementan el valor en uno. Pero, para las clases de C ++, llaman a diferentes operadores ( operator+=
vs. operator++
); de hecho, para algunas clases, como list<T>::iterator
, i += 1
no funciona y se debe usar i++
.
Además, producen valores diferentes. i += 1
produce i
después de incrementar (como un preincremento), mientras que i++
produce i
antes de incrementar. Así,
int a = 0, b = 0;
cout << (a+=1) << " " << b++ << endl;
imprime 1 0
. Como i += 1
es equivalente a un preincremento, en algunos casos, i += 1
puede resultar
Entonces, si bien son lo mismo para incrementar las variables, uno debe saber que no son sustitutos perfectos en todas las condiciones.
Los operadores ++
prefix o postfix cambian el valor de la variable.
int a = 0;
int b = a++; // b is equal to 0, a is equal to 1
O prefijo:
int a = 0;
int b = ++a; // b = 1, a = 1
Si se usa así, son lo mismo:
int a = 0;
++a; // 1
a++; // 2
a += 1; // 3
Me sorprende que nadie mencione que al menos para compiladores / computadoras viejas (básicamente cuando nació C y una década o dos después) += 1
será significativamente más lento que ++
. ++
es un incremento con el que la CPU probablemente tenga una sola instrucción. += 1
requiere cargar el valor 1 en un registro (probablemente guardando el valor de ... en alguna parte) y pedir una adición. No puedo decir si los compiladores actuales optimizan esto, pero sospecho que sí.
Soy nuevo en , pero aquí está mi valor de 2 peniques.
Si la pregunta es sobre + = y no + = 1. La declaración publicada fue;
Usualmente encuentro situaciones para usar ++ o + = 1, pero no puedo decir la diferencia.
Creo que el 1 podría haber sido fácilmente otro número o quizás mejor escrito como + =?
En términos del resultado, no hay diferencia (usando los valores de los carteles). Ambos aumentarán en uno, sin embargo, ++ solo aumentará en 1, mientras que + = aumentará en el valor especificado por el codificador, en el ejemplo de ederman, esto pasa a ser 1. Por ejemplo:
// Example 1:
num = 0;
num = ++;
// the result of num will be 1
// Example 2:
num = 0;
num = += 1;
// the result of num will be 1 the same as example 1
// Example 3:
num = 0;
num = += 2;
// the result of num will be 2.
// Example 4:
num = 0;
num = ++ 2;
// this would not compile as ++ will not except any value for the increment step it is assumed
// you will always want to increment by the value of 1
Entonces, si solo quieres incrementar un valor en 1, usaría ++ pero si necesitas aumentar más el 1 usa + =
Espero que sea útil.
num += 1
es bastante equivalente a ++num
.
Todas esas expresiones ( num += 1
, num++
y ++num
) incrementan el valor de num
en uno, pero el valor de num++
es el valor num
tenía antes de incrementarse.
Ilustración:
int a = 0;
int b = a++; // now b == 0 and a == 1
int c = ++a; // now c == 2 and a == 2
int d = (a += 1); // now d == 3 and a == 3
Usa lo que te plazca. Prefiero ++num
to num += 1
porque es más corto.
las operaciones de prefijo y postfijo son candidatos perfectos para preguntas de examen.
a = 0;
b = a++; // use the value and then increment --> a: 1, b: 0
a = 0;
b = ++a; // increment and then use the value --> a: 1, b: 1
+=
operación y su hermana -=
son soluciones más generales destinadas principalmente a ser usadas con diferentes números. Incluso se podría decir que son redundantes cuando se usan con 1
. Cuando se usan con 1
, en su mayoría actúan como una operación de prefijo . De hecho, en mi máquina producen el mismo código de máquina. Puede probar esto usando un programa de ejemplo como:
void foo() {
int a, b;
a = 0;
// use one of these four at a time
b = a++; // first case (different)
b = ++a; // second case
b = (a += 1); // third case
b = (a = a + 1); // fourth case
}
int main() {
foo();
return 0;
}
y desmontar en gdb
que daría:
primer caso ( a++
) (diferente)
(gdb) disassemble foo
Dump of assembler code for function foo:
0x00000000004004b4 <+0>: push %rbp
0x00000000004004b5 <+1>: mov %rsp,%rbp
0x00000000004004b8 <+4>: movl $0x0,-0x8(%rbp)
0x00000000004004bf <+11>: mov -0x8(%rbp),%eax
0x00000000004004c2 <+14>: mov %eax,-0x4(%rbp)
0x00000000004004c5 <+17>: addl $0x1,-0x8(%rbp)
0x00000000004004c9 <+21>: pop %rbp
0x00000000004004ca <+22>: retq
End of assembler dump.
segundo caso ( ++a
)
(gdb) disassemble foo
Dump of assembler code for function foo:
0x00000000004004b4 <+0>: push %rbp
0x00000000004004b5 <+1>: mov %rsp,%rbp
0x00000000004004b8 <+4>: movl $0x0,-0x8(%rbp)
0x00000000004004bf <+11>: addl $0x1,-0x8(%rbp)
0x00000000004004c3 <+15>: mov -0x8(%rbp),%eax
0x00000000004004c6 <+18>: mov %eax,-0x4(%rbp)
0x00000000004004c9 <+21>: pop %rbp
0x00000000004004ca <+22>: retq
End of assembler dump.
tercer caso ( a += 1
)
(gdb) disassemble foo
Dump of assembler code for function foo:
0x00000000004004b4 <+0>: push %rbp
0x00000000004004b5 <+1>: mov %rsp,%rbp
0x00000000004004b8 <+4>: movl $0x0,-0x8(%rbp)
0x00000000004004bf <+11>: addl $0x1,-0x8(%rbp)
0x00000000004004c3 <+15>: mov -0x8(%rbp),%eax
0x00000000004004c6 <+18>: mov %eax,-0x4(%rbp)
0x00000000004004c9 <+21>: pop %rbp
0x00000000004004ca <+22>: retq
End of assembler dump.
cuarto caso ( a = a + 1
)
(gdb) disassemble foo
Dump of assembler code for function foo:
0x00000000004004b4 <+0>: push %rbp
0x00000000004004b5 <+1>: mov %rsp,%rbp
0x00000000004004b8 <+4>: movl $0x0,-0x8(%rbp)
0x00000000004004bf <+11>: addl $0x1,-0x8(%rbp)
0x00000000004004c3 <+15>: mov -0x8(%rbp),%eax
0x00000000004004c6 <+18>: mov %eax,-0x4(%rbp)
0x00000000004004c9 <+21>: pop %rbp
0x00000000004004ca <+22>: retq
End of assembler dump.
Como puede ver, producen el mismo código de máquina incluso sin optimizaciones del compilador activadas, excepto en el primer caso que tiene addl
after mov
s. Esto significa que debe usar lo que quiera como usuario y dejar que el compilador haga el resto.
Y, por último, tenga en cuenta que los operadores primos *=
y /=
no tienen contrapartes de prefijo y prefijo .