3

Rust - Ownership ?

 2 years ago
source link: https://dev.to/higordiego/rust-ownership-1hka
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
DEV Community

Todos os programas têm que decidir de que forma vão utilizar a memória do computador durante sua execução.

Existe linguagens que abordam o garbage collection (coleta de lixo) que simplesmente buscam espaço em memória que não estão em uso naquele momento.

Outra abordagem em outras linguagens é que, o programador deve alocar o espaço em memória e liberar.

No Rust usa uma abordagem diferente que é memória gerenciada através de um sistema de posse que contém um conjunto de regras que isso é verificado em tempo de compilação.

Regras de Owneship

  • Cada valor em Rust possui uma variável que é dita seu owner (sua dona).
  • Pode apenas haver um owner por vez.
  • Quando o owner sai fora de escopo, o valor será destruído.

Para que possamos ilustrar o conjunto de regras precisamos de um tipo de dados que seja complexo abordagem porque esses dados são armazenados na pilha e assim retirada quando o escopo acaba.

Vamos para o exemplo.


fn main() {

    let x =  String::from("Higor Diego");
    println!("{}", x);

}

/*
  Higor Diego  
*/

Enter fullscreen modeExit fullscreen mode

Em post anteriores vimos string literais onde o valor da string é fixado elas são convenientes mas se adequam em situação que queremos textos em nossos programas. Uma das característica delas que são imutáveis.

No exemplo usamos o String::From o :: é um operador que nos permiti indicar o namespace da função from que se caracteriza como uma string.

Vamos para o exemplo abaixo.



fn main() {

    let mut x  =  String::from("Higor Diego");
    x.push_str(" é o meu nome");
    println!("{}", x);

}

/*
  Higor Diego é o meu nome
*/

Enter fullscreen modeExit fullscreen mode

Fica uma pergunta no ar, porque as String podem ser alterada e as literais não? O detalhe disso é como eles lidam com a memória.

Quando uma String literal é declarada já está explícito o conteúdo com isso injetado no software assim fazendo elas serem rápidas.

Segue o exemplo.


{
  let x = String::from("escopo");
}

Enter fullscreen modeExit fullscreen mode

No exemplo acima temos um escopo que é declarado pela chaves dentro dele temos uma variável x que é uma string após o fechamento da chaves a variável não é mais valida pois o escopo fechou.

No Rust quando a variável sai do escopo automaticamente chamamos uma função especial chamada drop. Parece simples mas quando temos múltiplas variáveis como seria ?

Segue o exemplo.


fn main() {
    let number_1 = 10;
    let number_2 = number_1;
}

Enter fullscreen modeExit fullscreen mode

No caso acima temos uma variável chamada number_1 que recebe um valor de 10 e temos number_2 que associada a variável anterior. Temos duas variáveis com o mesmo valor isso acontece porque números possuem um tamanho fixo.

No caso de uma String como seria ?


fn main() {
    let n_1 = String::from("higor");
    let n_2 = n_1;

    println!("{}", n_1);
}

/*
     --> main.rs:27:20
   |
25 |     let n_2 = n_1;
   |         --- value moved here
26 | 
27 |     println!("{}", n_1)
   |                    ^^^ value used here after move
   |
   = note: move occurs because `n_1` has type `std::string::String`, which does not implement the `Copy` trait

error: aborting due to previous error

*/

Enter fullscreen modeExit fullscreen mode

Se analisar o exemplo anterior com esse, seria basicamente a mesma coisa só que existe uma diferença, porque estamos falando de "cópia rasa" e "copia profunda".

O Rust nesse exemplo está invalidando a primeira variável no lugar de chamar a "copia rasa" isso é conhecido como move. Após a locação da variável para n_2 com n_1 o Rust libera o espaço de valor da n_1 em memória e a loca n_2 no seu lugar assim invalidando a variável n_1.

Para resolução vamos utilizar uma função chamada clone() que no caso seria uma copia profunda da variável declarada.

Segue o exemplo.


fn main() {
    let n_1 = String::from("higor");
    let n_2 = n_1.clone();

    println!("n_1: {}, n_2: {}", n_1, n_2);
}

/*
  n_1: higor, n_2: higor
*/


Enter fullscreen modeExit fullscreen mode

Vamos testar o mesmo conceito com funções.


fn main() {
  let x1 = retorna_string();
  let x2 = x1;
  println!("x1: {}, x2: {}", x1, x2);
}

fn retorna_string() -> String {
  return String::from("olá");
}
/*
 --> main.rs:4:30
  |
3 |   let x2 = x1;
  |       -- value moved here
4 |   println!("x1: {}, x2: {}", x1, x2);
  |                              ^^ value used here after move
  |
  = note: move occurs because `x1` has type `std::string::String`, which does not implement the `Copy` trait

error: aborting due to previous error
*/

Enter fullscreen modeExit fullscreen mode

Ahhhhh, mas está fácil. Para que possa corrigir só usar o clone().

Segue o exemplo.


fn main() {
  let x1 = retorna_string();
  let x2 = x1.clone();
  println!("x1: {}, x2: {}", x1, x2);
}

fn retorna_string() -> String {
  return String::from("olá");
}

*/
  x1: olá, x2: olá
*/

Enter fullscreen modeExit fullscreen mode

Então galera é isso, espero que tenham gostado até a próxima.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK