stringtranslate.com

Referencia (informática)

En programación de computadoras , una referencia es un valor que permite a un programa acceder indirectamente a un dato particular , como el valor de una variable o un registro , en la memoria de la computadora o en algún otro dispositivo de almacenamiento . Se dice que la referencia se refiere al dato y acceder al dato se llama desreferenciar la referencia. Una referencia es distinta del dato mismo.

Una referencia es un tipo de datos abstracto y puede implementarse de muchas maneras. Normalmente, una referencia se refiere a datos almacenados en la memoria de un sistema determinado y su valor interno es la dirección de memoria de los datos, es decir, una referencia se implementa como un puntero . Por esta razón, a menudo se dice que una referencia "señala" los datos. Otras implementaciones incluyen un desplazamiento (diferencia) entre la dirección del dato y alguna dirección "base" fija, un índice o identificador utilizado en una operación de búsqueda en una matriz o tabla , un identificador del sistema operativo , una dirección física en un dispositivo de almacenamiento o una dirección de red como una URL .

Representación formal

Una referencia R es un valor que admite una operación, dereference( R ), que produce un valor. Generalmente la referencia se escribe de manera que devuelva valores de un tipo específico, por ejemplo: [1] [2]

 Referencia de interfaz < T > { Valor T (); }   

A menudo la referencia también admite una operación de asignación store( R , x ), lo que significa que es una variable abstracta . [1]

Usar

Las referencias se utilizan ampliamente en programación , especialmente para pasar de manera eficiente datos grandes o mutables como argumentos a procedimientos , o para compartir dichos datos entre varios usos. En particular, una referencia puede apuntar a una variable o registro que contiene referencias a otros datos. Esta idea es la base del direccionamiento indirecto y de muchas estructuras de datos vinculados , como las listas vinculadas . Las referencias aumentan la flexibilidad en cuanto a dónde se pueden almacenar los objetos, cómo se asignan y cómo se pasan entre áreas de código . Siempre que se pueda acceder a una referencia a los datos, se puede acceder a los datos a través de ella y no es necesario mover los datos en sí. También facilitan el intercambio de datos entre diferentes áreas de código; cada uno mantiene una referencia a él.

Las referencias pueden causar una complejidad significativa en un programa, en parte debido a la posibilidad de referencias colgantes y salvajes y en parte porque la topología de los datos con referencias es un gráfico dirigido , cuyo análisis puede ser bastante complicado. No obstante, las referencias son aún más sencillas de analizar que los punteros debido a la ausencia de aritmética de punteros .

El mecanismo de referencias, si varía en su implementación, es una característica fundamental del lenguaje de programación común a casi todos los lenguajes de programación modernos. Incluso algunos lenguajes que no admiten el uso directo de referencias tienen algún uso interno o implícito. Por ejemplo, la convención de llamada por referencia se puede implementar con el uso explícito o implícito de referencias.

Ejemplos

Los punteros son el tipo de referencia más primitivo. Debido a su íntima relación con el hardware subyacente, son uno de los tipos de referencias más potentes y eficientes. Sin embargo, también debido a esta relación, los punteros requieren una sólida comprensión por parte del programador de los detalles de la arquitectura de la memoria. Debido a que los punteros almacenan la dirección de una ubicación de memoria, en lugar de un valor directamente, el uso inadecuado de los punteros puede provocar un comportamiento indefinido en un programa, particularmente debido a punteros colgantes o punteros salvajes . Los punteros inteligentes son estructuras de datos opacas que actúan como punteros pero a las que solo se puede acceder a través de métodos particulares.

Un identificador es una referencia abstracta y puede representarse de varias maneras. Un ejemplo común son los identificadores de archivos (la estructura de datos FILE en la biblioteca de E/S estándar de C ), que se utilizan para abstraer el contenido del archivo. Por lo general, representa tanto el archivo en sí, como cuando se solicita un bloqueo en el archivo, como una posición específica dentro del contenido del archivo, como cuando se lee un archivo.

En informática distribuida , la referencia puede contener más de una dirección o identificador; también puede incluir una especificación integrada de los protocolos de red utilizados para localizar y acceder al objeto al que se hace referencia, la forma en que se codifica o serializa la información. Así, por ejemplo, una descripción WSDL de un servicio web remoto puede verse como una forma de referencia; incluye una especificación completa de cómo localizar y vincularse a un servicio web en particular . Una referencia a un objeto distribuido en vivo es otro ejemplo: es una especificación completa sobre cómo construir un pequeño componente de software llamado proxy que posteriormente participará en una interacción entre pares y a través del cual la máquina local puede obtener acceso a datos que se replican o existen sólo como un flujo de mensajes débilmente consistente. En todos estos casos, la referencia incluye el conjunto completo de instrucciones, o una receta, sobre cómo acceder a los datos; en este sentido, cumple el mismo propósito que un identificador o dirección en la memoria.

Si tenemos un conjunto de claves K y un conjunto de objetos de datos D , cualquier función bien definida (de un solo valor) de K a D ∪ { nulo } define un tipo de referencia, donde nulo es la imagen de una clave que no hace referencia a algo significativo.

Una representación alternativa de dicha función es un gráfico dirigido llamado gráfico de alcanzabilidad. Aquí, cada dato está representado por un vértice y hay una arista de u a v si el dato en u se refiere al dato en v . El grado máximo de salida es uno. Estos gráficos son valiosos en la recolección de basura , donde se pueden usar para separar objetos accesibles de los inaccesibles .

Almacenamiento externo e interno

En muchas estructuras de datos, los objetos grandes y complejos se componen de objetos más pequeños. Estos objetos normalmente se almacenan de dos maneras:

  1. Con el almacenamiento interno, el contenido del objeto más pequeño se almacena dentro del objeto más grande.
  2. Con el almacenamiento externo, los objetos más pequeños se asignan en su propia ubicación y el objeto más grande solo almacena referencias a ellos.

El almacenamiento interno suele ser más eficiente, porque hay un costo de espacio para las referencias y los metadatos de asignación dinámica , y un costo de tiempo asociado con la desreferenciación de una referencia y con la asignación de memoria para los objetos más pequeños. El almacenamiento interno también mejora la localidad de referencia al mantener juntas en la memoria diferentes partes del mismo objeto grande. Sin embargo, existen diversas situaciones en las que se prefiere el almacenamiento externo:

Algunos lenguajes, como Java , Smalltalk , Python y Scheme , no admiten almacenamiento interno. En estos lenguajes, se accede uniformemente a todos los objetos a través de referencias.

Ayuda de idioma

Asamblea

En lenguaje ensamblador , es típico expresar referencias utilizando direcciones de memoria sin formato o índices en tablas. Funcionan, pero son algo complicados de usar, porque una dirección no dice nada sobre el valor al que apunta, ni siquiera qué tan grande es o cómo interpretarlo; dicha información está codificada en la lógica del programa. El resultado es que pueden producirse malas interpretaciones en programas incorrectos, provocando errores desconcertantes.

Ceceo

Una de las primeras referencias opacas fue la de la celda cons del lenguaje Lisp , que es simplemente un registro que contiene dos referencias a otros objetos Lisp, incluidas posiblemente otras celdas cons. Esta estructura simple se usa más comúnmente para construir listas enlazadas individualmente , pero también se puede usar para construir árboles binarios simples y las llamadas "listas de puntos", que terminan no con una referencia nula sino con un valor.

C/C++

El puntero sigue siendo uno de los tipos de referencias más populares en la actualidad. Es similar a la representación ensamblada de una dirección sin formato, excepto que lleva un tipo de datos estático que se puede usar en tiempo de compilación para garantizar que los datos a los que hace referencia no se malinterpreten. Sin embargo, debido a que C tiene un sistema de tipos débil que puede violarse mediante conversiones (conversiones explícitas entre varios tipos de punteros y entre tipos de punteros y números enteros), aún es posible una interpretación errónea, aunque más difícil. Su sucesor C++ intentó aumentar la seguridad de tipos de punteros con nuevos operadores de conversión, un tipo de referencia &y punteros inteligentes en su biblioteca estándar , pero aún conservaba la capacidad de eludir estos mecanismos de seguridad por motivos de compatibilidad.

fortran

Fortran no tiene una representación explícita de referencias, pero las usa implícitamente en su semántica de llamadas de llamada por referencia . Es mejor considerar una referencia de Fortran como un alias de otro objeto, como una variable escalar o una fila o columna de una matriz. No existe una sintaxis para desreferenciar la referencia o manipular el contenido del referente directamente. Las referencias de Fortran pueden ser nulas. Como en otros lenguajes, estas referencias facilitan el procesamiento de estructuras dinámicas, como listas enlazadas, colas y árboles.

Lenguajes orientados a objetos

Varios lenguajes orientados a objetos como Eiffel , Java , C# y Visual Basic han adoptado un tipo de referencia mucho más opaco, generalmente denominado simplemente referencia . Estas referencias tienen tipos como punteros C que indican cómo interpretar los datos a los que hacen referencia, pero son seguros en el sentido de que no pueden interpretarse como una dirección sin formato y no se permiten conversiones no seguras. Las referencias se utilizan ampliamente para acceder y asignar objetos. Las referencias también se utilizan en llamadas a funciones/ métodos o en el paso de mensajes, y los recuentos de referencias se utilizan con frecuencia para realizar la recolección de basura de objetos no utilizados.

Lenguajes funcionales

En Standard ML , OCaml y muchos otros lenguajes funcionales, la mayoría de los valores son persistentes: no se pueden modificar mediante asignación. Las "celdas de referencia" asignables proporcionan variables mutables , datos que se pueden modificar. Estas celdas de referencia pueden contener cualquier valor y, por lo tanto, se les asigna el tipo polimórficoα ref , donde αse reemplazará con el tipo de valor al que apunta. Estas referencias mutables pueden apuntar a diferentes objetos a lo largo de su vida. Esto permite, por ejemplo, construir estructuras de datos circulares. La celda de referencia es funcionalmente equivalente a una matriz mutable de longitud 1.

Para preservar la seguridad y las implementaciones eficientes, las referencias no se pueden convertir en tipos en ML ni se puede realizar aritmética de punteros. En el paradigma funcional, muchas estructuras que se representarían usando punteros en un lenguaje como C se representan usando otras facilidades, como el poderoso mecanismo de tipos de datos algebraicos . El programador puede entonces disfrutar de ciertas propiedades (como la garantía de inmutabilidad) mientras programa, aunque el compilador a menudo utiliza punteros de máquina "bajo el capó".

Perl/PHP

Perl admite referencias físicas, que funcionan de manera similar a las de otros lenguajes, y referencias simbólicas , que son simplemente valores de cadena que contienen los nombres de las variables. Cuando se desreferencia un valor que no es una referencia física, Perl lo considera una referencia simbólica y le da a la variable el nombre dado por el valor. [3] PHP tiene una característica similar en la forma de su $$varsintaxis. [4]

Pitón

Python incluye una amplia gama de referencias. Generalmente, los programadores utilizan id(var)para acceder a la dirección de referencia de una variable var. La referencia en Python es más compleja que C++ u otros lenguajes de programación.

Una constante (por ejemplo, un número entero 2) es un objeto en Python y, por tanto, tiene una referencia a una dirección fija. Cuando el programador llama a una a = 2, el programa crea un espacio de memoria para la consonante 2y organiza una referencia a ella. Luego, el programa vincula la referencia de aa la dirección de 2, lo que revela que cambiar el valor de una variable numérica cambia la referencia de la misma. Mientras que en los tipos mutables (por ejemplo, un listtipo), el cambio de valor no cambiará la referencia de la variable.

Cuando se pasa una variable como parámetro de función, la función obtiene la referencia de forma predeterminada, no su valor. Para tipos mutables, esto hace que la variable original sea fácil de modificar; para el tipo inmutable, modificar su valor en la función hará que la referencia de la variable temporal en la función se modifique a otro lugar, por lo tanto, no provocará que se cambie la variable original.

Ver también

Referencias

  1. ^ ab Sherman, Mark S. (abril de 1985). Paragon: un lenguaje que utiliza jerarquías de tipos para la especificación, implementación y selección de tipos de datos abstractos. Medios de ciencia y negocios de Springer. pag. 175.ISBN _ 978-3-540-15212-5.
  2. ^ "Referencia (Plataforma Java SE 7)". docs.oracle.com . Consultado el 10 de mayo de 2022 .
  3. ^ "perlref". perldoc.perl.org . Consultado el 19 de agosto de 2013 .
  4. ^ "Variables variables - Manual". PHP . Consultado el 19 de agosto de 2013 .

enlaces externos