Soy realmente nuevo en Swift y acabo de leer que las clases se pasan por referencia y que se copian las matrices / cadenas, etc.
¿Es el paso por referencia de la misma manera que en Objective-C o Java en el que realmente pasa "una" referencia o es el paso correcto por referencia?
swift
pass-by-reference
pass-by-value
pass-by-pointer
gran_profaci
fuente
fuente
Respuestas:
Tipos de cosas en Swift
La regla es:
Las instancias de clase son tipos de referencia (es decir, su referencia a una instancia de clase es efectivamente un puntero )
Las funciones son tipos de referencia
Todo lo demás es un tipo de valor ; "todo lo demás" simplemente significa instancias de estructuras e instancias de enumeraciones, porque eso es todo lo que hay en Swift. Las matrices y cadenas son instancias de estructura, por ejemplo. Usted puede pasar una referencia a una de esas cosas (como un argumento de función) mediante el uso
inout
y tomando la dirección, como se ha señalado newacct. Pero el tipo es en sí mismo un tipo de valor.Qué significan los tipos de referencia para usted
Un objeto de tipo de referencia es especial en la práctica porque:
La mera asignación o el paso a la función pueden producir múltiples referencias al mismo objeto
El objeto en sí es mutable incluso si la referencia a él es una constante (
let
explícita o implícita).Una mutación en el objeto afecta a ese objeto tal como lo ven todas las referencias a él.
Esos pueden ser peligros, así que esté atento. Por otro lado, pasar un tipo de referencia es claramente eficiente porque solo se copia y pasa un puntero, lo cual es trivial.
Qué significan los tipos de valor para usted
Claramente, pasar un tipo de valor es "más seguro" y
let
significa lo que dice: no se puede mutar una instancia de estructura o una instancia de enumeración a través de unalet
referencia. Por otro lado, esa seguridad se logra haciendo una copia separada del valor, ¿no es así? ¿No hace eso que pasar un tipo de valor sea potencialmente costoso?Bueno, sí y no. No es tan malo como podría pensar. Como ha dicho Nate Cook, pasar un tipo de valor no implica necesariamente copiar, porque
let
(explícito o implícito) garantiza la inmutabilidad, por lo que no es necesario copiar nada. E incluso pasar a unavar
referencia no significa que las cosas se copiarán, solo que pueden serlo si es necesario (porque hay una mutación). Los documentos le aconsejan específicamente que no se tuerza las bragas.fuente
inout
independiente del tipo. Si algo es paso por referencia es ortogonal a los tipos.Siempre es paso por valor cuando el parámetro no lo es
inout
.Siempre es de paso por referencia si el parámetro es
inout
. Sin embargo, esto es algo complicado por el hecho de que necesita usar explícitamente el&
operador en el argumento cuando se pasa a uninout
parámetro, por lo que es posible que no se ajuste a la definición tradicional de paso por referencia, donde pasa la variable directamente.fuente
inout
)inout
en realidad no se pasa por referencia sino copia-entrada-salida. Sólo garantiza que después de la llamada a la función se asignará un valor modificado al argumento original. Parámetros de entrada-salidaTodo en Swift se pasa por "copia" por defecto, así que cuando pasas un tipo de valor obtienes una copia del valor, y cuando pasas un tipo de referencia obtienes una copia de la referencia, con todo lo que eso implica. (Es decir, la copia de la referencia aún apunta a la misma instancia que la referencia original).
Utilizo comillas de miedo alrededor de la "copia" de arriba porque Swift hace mucha optimización; siempre que sea posible, no se copia hasta que haya una mutación o la posibilidad de mutación. Dado que los parámetros son inmutables de forma predeterminada, esto significa que la mayoría de las veces no se realiza ninguna copia.
fuente
Aquí hay una pequeña muestra de código para pasar por referencia. Evite hacer esto, a menos que tenga una razón sólida para hacerlo.
Llámalo así
fuente
inout
es un operador de copia de entrada y salida. Primero copiará en el objeto, luego sobrescribirá el objeto original después de que regrese la función. Si bien puede parecer lo mismo, existen diferencias sutiles.El blog Apple Swift Developer tiene una publicación llamada Value and Reference Types que proporciona una discusión clara y detallada sobre este mismo tema.
Citar:
La publicación del blog Swift continúa explicando las diferencias con ejemplos y sugiere cuándo usaría uno sobre el otro.
fuente
Las clases se pasan por referencias y otras se pasan por valor de forma predeterminada. Puede pasar por referencia utilizando la
inout
palabra clave.fuente
inout
es un operador de copia de entrada y salida. Primero copiará en el objeto, luego sobrescribirá el objeto original después de que regrese la función. Si bien puede parecer lo mismo, existen diferencias sutiles.Cuando usa inout con un operador infijo como + =, el símbolo de dirección & puede ignorarse. ¿Supongo que el compilador asume pasar por referencia?
origDictionary + = newDictionaryToAdd
Y muy bien, este diccionario 'agregar' solo escribe uno en la referencia original también, ¡tan genial para bloquear!
fuente
Clases y estructuras
Una de las diferencias más importantes entre estructuras y clases es que las estructuras siempre se copian cuando se pasan en su código, pero las clases se pasan por referencia.
Cierres
Si asigna un cierre a una propiedad de una instancia de clase y el cierre captura esa instancia haciendo referencia a la instancia o sus miembros, creará un ciclo de referencia fuerte entre el cierre y la instancia. Swift usa listas de captura para romper estos fuertes ciclos de referencia
ARC (recuento automático de referencias)
El recuento de referencias se aplica solo a instancias de clases. Las estructuras y enumeraciones son tipos de valor, no tipos de referencia, y no se almacenan ni se pasan por referencia.
fuente