Actualmente estoy aprendiendo C ++ y aprendí sobre el incremento hace un tiempo. Sé que puedes usar "++ x" para hacer el incremento antes y "x ++" para hacerlo después.
Aún así, realmente no sé cuándo usar cualquiera de los dos ... Nunca he usado realmente "++ x" y las cosas siempre funcionaron bien hasta ahora, entonces, ¿cuándo debería usarlo?
Ejemplo: En un bucle for, ¿cuándo es preferible utilizar "++ x"?
Además, ¿alguien podría explicar exactamente cómo funcionan las diferentes incrementos (o decrementaciones)? Yo realmente lo apreciaría.
fuente
x++
es un rvalue con el valor dex
antes del incremento,x++
es un lvalue con el valor dex
después de un incremento. Ninguna expresión garantiza que el valor real incrementado se vuelva a almacenar ax, solo se garantiza que suceda antes del siguiente punto de secuencia. 'después de procesar la declaración actual' no es estrictamente precisa ya que algunas expresiones tienen puntos de secuencia y algunas declaraciones son declaraciones compuestas.Scott Meyers te dice que prefieras el prefijo excepto en aquellas ocasiones en las que la lógica dicte que el prefijo es apropiado.
Elemento n. ° 6 de "C ++ más eficaz" : para mí es suficiente autoridad.
Para aquellos que no son dueños del libro, aquí están las citas pertinentes. Desde la página 32:
Y en la página 34:
fuente
i++
o++i
, el código generado es el mismo.++x
yx++
realmente importa, es mucho más importante que realmente use un compilador que pueda optimizar completa y adecuadamente cualquiera de las versiones sin importar la contexto. "Ya que estoy usando este viejo martillo de mierda, sólo puedo clavar clavos en un ángulo de 43,7 grados" es un mal argumento para construir una casa clavando clavos a sólo 43,7 grados. Utilice una mejor herramienta.Desde cppreference al incrementar iteradores:
El incremento previo no genera el objeto temporal. Esto puede marcar una diferencia significativa si su objeto es costoso de crear.
fuente
Solo quiero notar que el código generado a menudo es el mismo si usa el incremento pre / post donde la semántica (de pre / post) no importa.
ejemplo:
pre.cpp:
post.cpp:
_
fuente
std::map::iterator
? Por supuesto, los dos operadores son diferentes, pero tengo curiosidad por saber si el compilador optimizará postfijo a prefijo si no se usa el resultado. No creo que esté permitido, dado que la versión de postfix podría contener efectos secundarios.Lo más importante a tener en cuenta, en mi opinión, es que x ++ debe devolver el valor antes de que se produjera el incremento; por lo tanto, tiene que hacer una copia temporal del objeto (incremento previo). Esto es menos eficiente que ++ x, que se incrementa en el lugar y se devuelve.
Sin embargo, otra cosa que vale la pena mencionar es que la mayoría de los compiladores podrán optimizar esas cosas innecesarias cuando sea posible, por ejemplo, ambas opciones conducirán al mismo código aquí:
fuente
Estoy de acuerdo con @BeowulfOF, aunque para mayor claridad siempre abogaría por dividir las declaraciones para que la lógica sea absolutamente clara, es decir:
o
Entonces, mi respuesta es que si escribe un código claro, esto rara vez debería importar (y si importa, entonces su código probablemente no sea lo suficientemente claro).
fuente
Solo quería volver a enfatizar que se espera que ++ x sea más rápido que x ++, (especialmente si x es un objeto de algún tipo arbitrario), por lo que, a menos que sea necesario por razones lógicas, se debe usar ++ x.
fuente
Explicaste la diferencia correctamente. Solo depende de si desea que x se incremente antes de cada ejecución a través de un bucle, o después de eso. Depende de la lógica de su programa, lo que sea apropiado.
Una diferencia importante cuando se trata de iteradores STL (que también implementan estos operadores) es que ++ crea una copia del objeto al que apunta el iterador, luego incrementa y luego devuelve la copia. ++, por otro lado, hace el incremento primero y luego devuelve una referencia al objeto al que apunta ahora el iterador. Esto es principalmente relevante cuando cada bit de rendimiento cuenta o cuando implementa su propio iterador STL.
Editar: se corrigió la confusión de notación de prefijo y sufijo
fuente
Ejemplo 1:
Cuando varios valores se conectan en cascada con << usando cout , los cálculos (si los hay) se realizan de derecha a izquierda, pero la impresión se realiza de izquierda a derecha, por ejemplo, (si val si inicialmente 10)
resultará en
Ejemplo 2:
En Turbo C ++, si se encuentran múltiples apariciones de ++ o (en cualquier forma) en una expresión, primero se calculan todas las formas de prefijo, luego se evalúa la expresión y finalmente se calculan las formas de sufijo, por ejemplo,
Su salida en Turbo C ++ será
Mientras que su salida en el compilador moderno será (porque siguen estrictamente las reglas)
expresiones varían de un compilador a otro.
fuente
Comprender la sintaxis del lenguaje es importante cuando se considera la claridad del código. Considere copiar una cadena de caracteres, por ejemplo, con un incremento posterior:
Queremos que el ciclo se ejecute encontrando el carácter cero (que prueba falso) al final de la cadena. Eso requiere probar el valor previo al incremento y también incrementar el índice. Pero no necesariamente en ese orden, una forma de codificar esto con el preincremento sería:
Es una cuestión de gusto que es más claro y si la máquina tiene un puñado de registros, ambos deberían tener el mismo tiempo de ejecución, incluso si una [i] es una función que es cara o tiene efectos secundarios. Una diferencia significativa podría ser el valor de salida del índice.
fuente