2008-11-13 16 views
8

Siempre me he preguntado por qué una operación tan simple y básica como intercambiar los contenidos de dos variables no está incorporada en muchos idiomas.¿Por qué no existe un operador de intercambio/intercambio en lenguaje imperativo o OO como C/C++/C#/Java ...?

Es uno de los ejercicios de programación más básicos en las clases de informática; se usa mucho en muchos algoritmos (por ejemplo, clasificación); de vez en cuando uno lo necesita y uno debe usar una variable temporal o usar una plantilla/función genérica.

Incluso es una instrucción básica de la máquina en muchos procesadores, por lo que se optimizará el esquema estándar con una variable temporal.

Se han creado muchos operadores menos obvios, como los operadores de asignación (por ejemplo, + =, que probablemente se creó para reflejar las instrucciones acumulativas de la máquina, por ejemplo, agregar ax, bx), o el ?? operador en C#.

Entonces, ¿cuál es el motivo? ¿O existe realmente y siempre me lo perdí?

+0

Buenas preguntas. También me he preguntado sobre esto, aunque las respuestas tienen sentido. – pro3carp3

+1

La declaración SWAP * does * existe en QBasic. – dan04

+0

Más interesante que una macro 'cambiar dos variables' sería algo que se comportara como el operador de coma, pero cuyo valor fuera el del primer operando. Imagine que el operador se escribiera como "=:" (realmente no sé qué notación sería buena). Entonces "x = (y =: y = x)" cambiaría x e y. Otros usos serían, p. "return (y =: y + = 4)" sería conceptualmente similar al operador de incremento posterior, pero incrementándose en 4 en lugar de uno. – supercat

Respuesta

11

En mi experiencia, no es que comúnmente se necesita en aplicaciones reales, además de los algoritmos de clasificación ya mencionadas y, ocasionalmente, en bajo nivel de hardware, así que en mi opinión es un propósito demasiado especial para tenerlo en un lenguaje de propósito general.

Como también se ha mencionado, no todos los procesadores lo admiten como una instrucción (y muchos no lo admiten para objetos más grandes que una palabra). Por lo tanto, si fuera compatible con alguna semántica adicional útil (por ejemplo, una operación atómica) sería difícil de admitir en algunos procesadores, y si no tuviera la semántica adicional, entonces es simplemente (rara vez se usa) azúcar sinatatico.

Los operadores de asignación (+ = etc) fueron compatibles porque son mucho más comunes en los programas del mundo real, por lo que el azúcar sintético que proporcionan es más útil y también como optimización. Recuerde las fechas de C de finales de los años 60/principios de los 70, y la optimización del compilador no era tan avanzada (y las máquinas con menos capacidad, por lo que no quería pases de optimización largos de todos modos).

Paul

+0

Buena respuesta. Pero hay más algoritmos en los que se usa: algoritmo Fisher-Yales (versión moderna), algoritmo Steinhaus-Johnson-Trotter, Matrix-Tranposition. Y en los más especializados, donde se usa como argumento para reducir la complejidad del espacio. Admito que estos son casos especializados. –

+1

"estos son casos especiales" Exactamente. –

+0

Un compilador de optimización aún puede usar instrucciones de intercambio nativo cada vez que detecta el patrón, por lo que ni siquiera es necesario para los casos especializados citados. –

0

Usted tiene la XOR operator que hace una sustitución de variables de tipo primitivo ...

+0

que puede causar un error si las dos cosas que estás intercambiando tienen la misma ubicación de almacenamiento sin embargo. Los pondrá a cero. También me han dicho que en los procesadores modernos, es menos eficiente que simplemente usar una variable temporal. –

3

Es un ejemplo ampliamente utilizado en cursos de informática, pero casi nunca se me encuentro que lo necesitan en código real - mientras que yo utilizo + = con mucha frecuencia.

Sí, en la ordenación sería útil, pero no suele tener que implementar la clasificación usted mismo, por lo que la cantidad de usos reales en el código fuente aún sería muy baja.

+0

El intercambio de dos valores no es común, pero es bastante común querer guardar y leer un valor l simultáneamente. En cierto sentido, eso es lo que hacen los operadores postfix ++ y - (hacen una tienda de un valor modificado, pero el valor propagado al resto de la expresión es el valor previo a la actualización). – supercat

-1

Creo que se olvidaron de agregarlo :-) Sí, no todas las CPU tienen este tipo de instrucciones, ¿y qué? Tenemos muchas otras cosas que la mayoría de las CPU no tienen instrucciones para calcular. ¡Sería mucho más fácil/claro y también más rápido (por intrínseco) si lo tuviéramos!

+0

no sería necesariamente más rápido - el compilador podría inline la llamada a cambiar (y me imagino que algunos ya lo hacen) si realmente es el rendimiento crítico. –

+0

¿Qué pasa con el hardware subyacente? Si tuviera instrucciones XCHG o similares, el intercambio se realizaría sin necesidad de una variable temporal y se ejecutaría más rápido. ¡Hay más en lo intrínseco que en la línea! – Malkocoglu

+0

... y hay más en la optimización que en la línea. Los compiladores son capaces de descifrar cuándo se está produciendo un intercambio (no es * que * difícil identificar una variable de temperatura y usar XCHG en su lugar). – Imagist

4

C++ does have swapping.

#include <algorithm> 
#include <cassert> 

int 
main() 
{ 
    using std::swap; 
    int a(3), b(5); 
    swap(a, b); 
    assert(a == 5 && b == 3); 
} 

Además, puede especializarse swap para este tipo de encargo también!

+2

Esto es solo una función definida. Lo que quise decir fue, por qué no está integrado directamente. –

Cuestiones relacionadas