Sou muito novo no Swift e acabei de ler que as classes são passadas por referência e os arrays / strings etc. são copiados.
A passagem por referência é da mesma maneira que em Objective-C ou Java em que você realmente passa "a" referência ou é passagem por referência adequada?
swift
pass-by-reference
pass-by-value
pass-by-pointer
gran_profaci
fonte
fonte
Respostas:
Tipos de coisas em Swift
A regra é:
Instâncias de classe são tipos de referência (ou seja, sua referência a uma instância de classe é efetivamente um ponteiro )
Funções são tipos de referência
Todo o resto é um tipo de valor ; "todo o resto" significa simplesmente instâncias de structs e instâncias de enums, porque isso é tudo que existe no Swift. Arrays e strings são instâncias de struct, por exemplo. Você pode passar uma referência a uma dessas coisas (como um argumento de função) usando
inout
e tomando o endereço, como newacct apontou. Mas o próprio tipo é um tipo de valor.O que os tipos de referência significam para você
Um objeto de tipo de referência é especial na prática porque:
A mera atribuição ou passagem para uma função pode gerar várias referências ao mesmo objeto
O próprio objeto é mutável, mesmo se a referência a ele for uma constante (
let
explícita ou implícita).Uma mutação no objeto afeta esse objeto como visto por todas as referências a ele.
Esses podem ser perigos, então fique de olho. Por outro lado, passar um tipo de referência é claramente eficiente porque apenas um ponteiro é copiado e passado, o que é trivial.
O que os tipos de valor significam para você
Claramente, passar um tipo de valor é "mais seguro" e
let
significa o que diz: você não pode transformar uma instância de struct ou de enum por meio de umalet
referência. Por outro lado, essa segurança é alcançada fazendo uma cópia separada do valor, não é? Isso não torna a passagem de um tipo de valor potencialmente cara?Bem, sim e não. Não é tão ruim quanto você imagina. Como disse Nate Cook, passar um tipo de valor não implica necessariamente em copiar, porque
let
(explícito ou implícito) garante imutabilidade, então não há necessidade de copiar nada. E mesmo passar para umavar
referência não significa que as coisas serão copiadas, apenas que podem ser se necessário (porque há uma mutação). Os médicos aconselham especificamente que você não confunda suas calcinhas.fonte
inout
independente do tipo. Se algo é passado por referência é ortogonal aos tipos.É sempre passado por valor quando o parâmetro não é
inout
.É sempre passado por referência se o parâmetro for
inout
. No entanto, isso é um pouco complicado pelo fato de você precisar usar explicitamente o&
operador no argumento ao passar para uminout
parâmetro, portanto, pode não se encaixar na definição tradicional de passagem por referência, em que você passa a variável diretamente.fonte
inout
)inout
na verdade, não é passado por referência, mas copiado e copiado . Garante apenas que, após a chamada da função, o valor modificado será atribuído ao argumento original. Parâmetros de entradaTudo em Swift é passado por "cópia" por padrão, então quando você passa um tipo de valor, você obtém uma cópia do valor, e quando você passa um tipo de referência, você obtém uma cópia da referência, com tudo o que isso implica. (Ou seja, a cópia da referência ainda aponta para a mesma instância da referência original.)
Eu uso aspas em torno da "cópia" acima porque o Swift faz muitas otimizações; sempre que possível, ele não copia até que haja uma mutação ou a possibilidade de mutação. Como os parâmetros são imutáveis por padrão, isso significa que na maioria das vezes nenhuma cópia realmente acontece.
fonte
Aqui está um pequeno exemplo de código para passar por referência. Evite fazer isso, a menos que tenha um forte motivo para isso.
Chame assim
fonte
inout
é um operador de cópia dentro e fora. Ele primeiro copiará no objeto e, em seguida, substituirá o objeto original após o retorno da função. Embora possa parecer o mesmo, existem diferenças sutis.O blog do desenvolvedor Apple Swift tem uma postagem chamada Tipos de valor e referência que fornece uma discussão clara e detalhada sobre esse tópico.
Citar:
A postagem do blog do Swift continua a explicar as diferenças com exemplos e sugere quando você deve usar um em vez do outro.
fonte
As classes são passadas por referências e outras são passadas por valor padrão. Você pode passar por referência usando a
inout
palavra - chave.fonte
inout
é um operador de cópia dentro e fora. Ele primeiro copiará no objeto e, em seguida, substituirá o objeto original após o retorno da função. Embora possa parecer o mesmo, existem diferenças sutis.Quando você usa inout com um operador infixo, como + =, o símbolo de endereço & pode ser ignorado. Eu acho que o compilador assume passagem por referência?
origDictionary + = newDictionaryToAdd
E agradavelmente, este dicionário 'adiciona' só faz uma gravação na referência original também, tão bom para travar!
fonte
Classes e estruturas
Uma das diferenças mais importantes entre estruturas e classes é que as estruturas são sempre copiadas quando são transmitidas em seu código, mas as classes são transmitidas por referência.
Fechamentos
Se você atribuir um encerramento a uma propriedade de uma instância de classe e o encerramento capturar essa instância referindo-se à instância ou a seus membros, você criará um forte ciclo de referência entre o encerramento e a instância. Swift usa listas de captura para quebrar esses fortes ciclos de referência
ARC (contagem automática de referência)
A contagem de referência se aplica apenas a instâncias de classes. Estruturas e enumerações são tipos de valor, não tipos de referência e não são armazenadas e passadas por referência.
fonte