Pasar parámetros por valor y por referencia

3,239 views
Skip to first unread message

Analyzer

unread,
Mar 7, 2013, 10:44:44 AM3/7/13
to mundovis...@googlegroups.com, zorrosm...@googlegroups.com, apren...@googlegroups.com
Veo que en varios documentos de diferentes lenguajes menciona lo de pasar parametros por referencia.

¿Como es la cosa?...

Esos conceptos los he visto ultimamente tanto en VFP como en VB.NET y ahora también en PHP.

¿Cuál es la diferencia básica?.

Esta fue la respuesta de un compañero:

**************

Para que entiendas el pase de parámetros por valor y por referencia empezaré por lo básico.

Cada ubicación de memoria siempre tiene un número guardado en ella. Una "ubicación de memoria" corresponde a un byte, o sea 8 bits y por lo tanto hay 256 valores posibles en ella.

¿Está claro hasta allí?

Por ejemplo, en la ubicación 25678 está el número 125. Y en la ubicación 30210 está el número 233.

Cuando a una función o a un procedimiento le envías un parámetro por "valor" lo que haces es enviarle el número que está en una posición de memoria. Por ejemplo, si envías por "valor" el contenido de la ubicación 25678 estás enviando el número 125.

¿Se entiende?

En cambio si envías por "referencia" estás enviando la ubicación de memoria, no el contenido de esa ubicación de memoria. En este ejemplo, estarías enviando 25678.

En el primer caso envías el número 125, en el segundo caso el lugar donde se encuentra el número 125 (en este ejemplo: 25678).

¿Qué sucede si esa función o procedimiento cambia el valor del parámetro recibido? Supongamos que cambia el valor del parámetro a 200.

Si enviaste por "valor", en la ubicación 25678 seguirá estando el número 125 porque ese número nunca fue cambiado, lo que se cambió de 125 a 200 fue el número que recibió la función o procedimiento.

En cambio, si enviaste "por referencia" ahora en la ubicación 25678 estará el número 200 porque se cambió el número que estaba allí.

En Visual FoxPro podrías escribir un programita como este:

CLEAR

NUM = 125
=DOBLE(NUM)
? NUM
?
NUM = 125
=DOBLE(@NUM)
? NUM
?
FUNCTION DOBLE
PARAMETERS MINUMERO
  MINUMERO = MINUMERO * 2
RETURN .T.

La forma de enviar un parámetro por referencia en Visual FoxPro es con el símbolo de arroba.

*****************

Ya corrí el programita.

En el primer caso no cambia y pone 125

En el segundo caso actualiza el valor y pone 250

Entiendo que cuando es por Referencia se ocupa el mismo lugar en memoria, pero por qué en el ejemplo no se actualiza el valor, si se supone que el valor debería multiplicarse por 2, independientemente de como se ubique en la memoria?..

Como se aplicarían ambos casos en la práctica?..

Saludos!

Carlos Miguel FARIAS

unread,
Mar 7, 2013, 11:13:01 AM3/7/13
to mundovis...@googlegroups.com
Decís que cambia el valor y luego decís que no, que dices?
No estas entendiendo nada, o no prestas atención al código super explicito que te paso el colega!

Cuando paso por valor, el valor de Num se copia al área del parámetro en la función (el parámetro se llama MiNumero)
Se hace la multiplicación, pero el valor no es retornado por lo que MiNumero funciona como variable local y al terminar la función se pierde.
En cambio cuando se pasa por referencia, lo que se pasa a la función es la dirección en memoria de Num (*)  (en el programa principal) y cuando en la función se hace la operación, el resultado es alojado en la dirección de memoria de Num, de ahí que cuando se imprime en el programa principal, el valor sale duplicado.
(*) VFP almacena todos sus datos en un array interno, que  accede por nombre (al pasar por referencia, lo que hace un nombre es apuntar al otro).
En la práctica, (y en fox por omisión) los valores a las funciones se pasan por valor y en los procedimientos (DO ... WITH ...) por referencia.
La idea es que cuando pasas parámetro por valor, te interesa preservar el valor de la variable pasada (si pasas una constante, si o si se pasa por valor).
Cuando pasas por referencia, la intención generalmente es que la función/procedimiento/método (todos trabajan igual) modifiquen el dato pasado.
Eso no es necesariamente obligatorio. A veces es indispensable.
Por ejemplo, si tienes un arreglo llamado Arreglo

x = unaFuncion(Arreglo) && pasa el primer elemento del arreglo y por valor
x = unaFuncion(@Arreglo) && pasa el arreglo completo

O sea que para pasar un arreglo completo, tienes que pasarlo por referencia. Más allá de que quieras modificarlo o no en la función.
Además, más allá de la modificación o no de los datos dentro de la función, es más rápido pasar parámetros por referencia que por valor (salvo que estés pasando enteros).
Otra ventaja de pasar por referencia es que, puedes indirectamente obtener mas de un valor de retorno sin muchas vueltas.

x = unaFuncion(@a, @b, @c)

Podrías obtener directamente 4 valores de retorno, uno en x, como era de esperar y 3 más en a, b y c.
Saludos: Miguel, La Pampa (RA)

--
_______________________________________________________________
Has recibido este mensaje porque estás suscrito al Grupo "Mundo Visual
FoxPro" de Grupos de Google.
 
Para anular la suscripción a este grupo, envía un mensaje a:
mundovisualfox...@googlegroups.com
---
Has recibido este mensaje porque estás suscrito al grupo "Mundo Visual FoxPro" de Grupos de Google.
Para anular la suscripción a este grupo y dejar de recibir sus correos electrónicos, envía un correo electrónico a mundovisualfox...@googlegroups.com.
Para obtener más opciones, visita https://groups.google.com/groups/opt_out.
 
 

Analyzer

unread,
Mar 7, 2013, 3:20:35 PM3/7/13
to mundovis...@googlegroups.com
Vuelvo a refrasear por si no lo expliqué bien..

CLEAR

NUM = 125
=DOBLE(NUM)
? NUM
?
NUM = 125
=DOBLE(@NUM)
? NUM
?
FUNCTION DOBLE
PARAMETERS MINUMERO
  MINUMERO = MINUMERO * 2
RETURN .T.

La forma de enviar un parámetro por referencia en Visual FoxPro es con el símbolo de arroba.


Ya corrí el programita.

En el primer caso no cambia y pone 125

En el segundo caso actualiza el valor y pone 250

Entiendo que cuando es por Referencia se ocupa el mismo lugar en memoria, pero por qué en el ejemplo:

1. No se actualiza la cantidad cuando se pasa el parámetro por valor, si se supone que el valor debería multiplicarse por 2, independientemente de como se ubique en la memoria?..

2. En cambio al pasar el parametro por referencia si actualiza la cantidad correctamente.

Que no debería efectuarse la multiplicación independientemente de lo que ocurra en memoria...?  Esa es la pregunta básicamente..

Analyzer

unread,
Mar 7, 2013, 3:24:34 PM3/7/13
to mundovis...@googlegroups.com
CMF,

Por alguna razón percibo un grado de estrés en aumento... Respire.. Relax..

La vida es bella jeje

Saludos!

Carlos Miguel FARIAS

unread,
Mar 7, 2013, 6:28:46 PM3/7/13
to mundovis...@googlegroups.com
understand?, entendiste, comprendre?, komprenas?, intelligitis?, entender?, פֿאַרשטיין

Analyzer

unread,
Mar 8, 2013, 10:41:58 AM3/8/13
to mundovis...@googlegroups.com
Esto es lo que me es dificil captar. Lo de cuando es "por valor".

"Cuando paso por valor, el valor de Num se copia al área del parámetro en la función (el parámetro se llama MiNumero)

Se hace la multiplicación, pero el valor no es retornado por lo que MiNumero funciona como variable local y al terminar la función se pierde."


Mi pregunta basica es esta en base al ejemplo:

1. No se actualiza la cantidad cuando se pasa el parámetro por valor, si se supone que el valor debería multiplicarse por 2, independientemente de como se ubique en la memoria?..

Al final no me queda claro si es algo que deba preocuparme o el VFP lo maneja el mismo y cuando el programador aplicaría cada caso en la práctica..

Saludos!

HernanCano

unread,
Mar 8, 2013, 8:02:32 PM3/8/13
to Mundo Visual FoxPro

NUM es una vble de memoria.
MINUMERO es un parámetro que recibe la función DOBLE.

Con @ le indicamos a la función que sí cambie el valor de la vble NUM
cuando dentro de la función haga algún cálculo con la vble.

Cuando escribimos =DOBLE(NUM) le decimos a DOBLE que no vaya a cambiar
el valor de NUM cualq sea el cálculo que haga (adentro puede cambiar,
pero al regresar respete el inicial).

Cuando escribimos =DOBLE(@NUM) le decimos a DOBLE que Sí puede cambiar
el valor de NUM cuando haga algún cálculo adentro (según la operación
matemática empleada).


Mensaje adicional:
Las negrillas funcionan en el correo, pero no en el portal
MundoVisualFoxPro, que es el que en última instancia recibe.

¿Vale?


On 8 mar, 10:41, Analyzer <thenewinquire...@gmail.com> wrote:
> Esto es lo que me es dificil captar. Lo de cuando es "por valor".
>
> "Cuando paso por valor, el valor de Num se copia al área del parámetro en
> la función (el parámetro se llama MiNumero)
> *Se hace la multiplicación, pero el valor no es retornado* por lo que
> MiNumero funciona como variable local y al terminar la función se pierde."
>
> Mi pregunta basica es esta en base al ejemplo:
>
> *1. No se actualiza la cantidad cuando se pasa el parámetro por valor, si
> se supone que el valor debería multiplicarse por 2, independientemente de
> como se ubique en la memoria?..*

Julio Cordova Gmail

unread,
Mar 8, 2013, 8:11:39 PM3/8/13
to mundovis...@googlegroups.com
Basico y elemental

Enviado desde mi Móvil LG

HernanCano <jherna...@gmail.com> escrito:

Analyzer

unread,
Mar 9, 2013, 12:37:59 AM3/9/13
to mundovis...@googlegroups.com
Gracias amigo Hernan Cano. Hasta ahora su explicación ha sido la mas sencilla y clara.

Saludos!


Analyzer

unread,
Mar 19, 2013, 8:10:15 PM3/19/13
to zorrosm...@googlegroups.com, mundovis...@googlegroups.com, apren...@googlegroups.com
Vaya.. Bien explicado y con ejemplos sencillos. No podría pedir mas..

Muy agradecido Fernando D. Bozzo.

Saludos!


El 19 de marzo de 2013 17:12, Fernando D. Bozzo <fdb...@gmail.com> escribió:
Hola Analyzer:

Respecto del uso de uno u otro, te doy un ejemplo:

Imaginate un método imprimir_pagina al que le pasás 3 datos (texto, tipo_hoja, copias)
y necesitás que te devuelva otros 3 datos (estado_impresion, paginas, nivel_tinta)

Como sabés, un método solo puede devolver un valor (numérico, fecha, carácter, objeto, etc) o como mucho una concatenación de valores, pero en una única cadena. ¿Qué pasa si necesitás que te devuelva más valores por separado? Lo que se hace es usar parámetros de "retorno", y para que estos puedan ser modificados por el método llamado, deben pasarse por referencia (como @variable)

Volviendo al caso del método imprimir_pagina del ejemplo, los primeros 3 parámetros se deben pasar por valor porque no te interesa (no querés) que su valor sea cambiado dentro del método, en cambio los otros 3 parámetros los enviás vacíos, porque esperás que el método te los complete con datos de verdad, para poder usarlos o presentarlos luego.

Por ejemplo: crea un programa llamado imprimir_pagina, así:

MODIFY COMMAND imprimir_pagina

Y dentro ponele este código:

LPARAMETERS tcTexto, tcTipo_hoja, tnCopias, @tcEstado_impresion, @tnPaginas, @tnNivel_tinta )
tcEstado_impresion = "OK"
tnPaginas = 3
tnNivel_tinta = 60
RETURN

Finalmente guardalo cerrando la ventana o con CTRL+W

Ahora, este método lo usarías así desde la ventana de comandos, luego de inicializar las variables y de setear los valores de entrada de a una línea por vez:

texto = "Este es un texto para imprimir"
tipo_hoja = "A4"
copias = 2
estado_impresion = ""
nivel_tinta = 0
paginas = 0

imprimir_pagina( texto, tipo_hoja, copias, @estado_impresion, @paginas, @nivel_tinta )

Si ahora escribís esto:

CLEAR
LIST MEMORY LIKE *

vas a poder ver que las últimas 3 variables que estaban vacías (estado_impresion, paginas, nivel_tinta) fueron rellenadas por el método con los valores "OK", 3 y 60.

Espero que ya te quede más claro.


Saludos.-

--
Has recibido este mensaje porque estás suscrito al grupo "Zorrosmexicanos" de Grupos de Google.
Para anular la suscripción a este grupo y dejar de recibir sus correos electrónicos, envía un correo electrónico a zorrosmexican...@googlegroups.com.
Para publicar una entrada en este grupo, envía un correo electrónico a zorrosm...@googlegroups.com.
Visita este grupo en http://groups.google.com/group/zorrosmexicanos?hl=es.

Analyzer

unread,
Oct 30, 2013, 11:52:06 AM10/30/13
to mundovis...@googlegroups.com
Curiosamente, la explicación más simple y comprensible de este tema la encontré en un manual de otro lenguaje, pero la idea parece ser la misma en VFP: 

En PHP, las variables siempre se asignan por valor. Esto significa que cuando se asigna una expresión a una variable, el valor íntegro de la expresión original se copia en la variable de destino. Esto quiere decir que, por ejemplo, después de asignar el valor de una variable a otra, los cambios que se efectúen a una de esas variables no afectará a la otra.

PHP ofrece otra forma de asignar valores a las variables: asignar por referencia. Esto significa que la nueva variable simplemente referencia (en otras palabras, "se convierte en un alias de" ó "apunta a") la variable original. Los cambios a la nueva variable afectan a la original, y viceversa. Esto también significa que no se produce una copia de valores; por tanto, la asignación ocurre más rápidamente. De cualquier forma, cualquier incremento de velocidad se notará sólo en los bucles críticos cuando se asignen grandes matrices u objetos.

Saludos!
Reply all
Reply to author
Forward
0 new messages