Rust - References e Borrowing
References e Borrowing
Através do uso de referencias podemos emprestar uma variável para uma função sem ter que lhe transferir a sua propriedade ‘onwer’
|
|
No exemplo acima s1 foi criado na ‘Linha A1’. Logo após emprestamos por referencia a variável s1 para a função ‘imprimir_string_e_tamanho’ que por sua vez imprime em ‘Linha B1’ e ‘Linha B2’ os valores da variável.
Note que após a ‘Linha B2’ o escopo da função ‘imprimir_string_e_tamanho’ chega ao fim e as variáveis que pertencem a essa função são desalocadas.
Note também que acessamos a variável s1 na ‘Linha A3’ e na ‘Linha A4’. Isso só é possível por causa do conceito de ‘References’ e ‘Borrowing’. Quando utilizamos a chave ‘&’ estamos dizendo ao compilador RUST que queremos emprestar e não transferir a variável para a função chamada.
|
|
O exemplo acima demonstra como ter o mesmo resultado quando não utilizamos referencias. Nesse caso estamos passando o ‘onwer’ de ‘s1’ para a função ‘imprimir_string_e_tamanho’ e depois passando o ‘onwer’ de s por retorno para a função ‘main’
Referencias mutáveis
|
|
Para modificar a referencia tudo o que precisamos fazer é torná-la mutável.
Porem, RUST tem uma regra para esses momentos onde estamos trabalhando com referencias mutáveis.
A regra é:
- Você só pode possuir uma referência mutável para um endereço de memória por escopo.
Isso significa que:
|
|
Na ‘Linha 05’ estamos quebrando essa regra. ‘mr2’ é a segunda referencia mutável para a área de memória apontada por ’s'. Graças a essa regra o nosso código acima não terá sua compilação finalizada e recebera um erro do RUST.
Esta regra introduzida pelo compilador RUST protege o programador de ‘data race’ que acontece quando o cenário abaixo é satisfeito:
- Dois ou mais ponteiros acessam o mesmo conteúdo apontado pelo endereço de memória.
- Pelo menos um dos ponteiros esta sendo usado para escrever dados
- Não existe nenhum mecanismo para sincronizar o acesso ao dado
O cenário acima pode causar um comportamento inesperado no seu programa e momentos como esse são difíceis de debugar.
Um outro problema ocorre quando combinamos referências mutáveis com referências não mutáveis que apontam para o mesmo endereço de memória
|
|
Não podemos ter referências mutáveis e não mutáveis trabalhando junto em RUST pois usuários de ‘r1’ esperam que o valor de s nunca mude e para respeitar esse compromisso RUST não pode deixar que ‘mr1’ exista.
Ponteiros que apontam para nada
Em linguagens como C é possível acessar um ponteiro que teve sua área de memória liberada.
|
|
O código acima pode gerar uma interrupção em seu programa ou um comportamento inesperado. O mesmo código em RUST seria:
|
|
Porem, o código acima retorna um erro de compilação dizendo que o tempo de vida de ’s' já acabou quando esta é retornada por parâmetro para a função main.
Para que a lógica do código acima funcione precisamos transferir a propriedade para evitar que a variável seja desalocada ao fim do escopo de ‘aloca_mem’
|
|