Ferrugem - Propriedade

A memória para um programa pode ser alocada da seguinte forma -

  • Stack
  • Heap

Pilha

Uma pilha segue a ordem do último na primeira a sair. A pilha armazena valores de dados cujo tamanho é conhecido no momento da compilação. Por exemplo, uma variável de tamanho fixo i32 é candidata à alocação de pilha. Seu tamanho é conhecido em tempo de compilação. Todos os tipos escalares podem ser armazenados na pilha, pois o tamanho é fixo.

Considere um exemplo de string, que recebe um valor no tempo de execução. O tamanho exato de tal string não pode ser determinado em tempo de compilação. Portanto, não é um candidato para alocação de pilha, mas para alocação de heap.

Heap

A memória heap armazena valores de dados cujo tamanho é desconhecido no momento da compilação. Ele é usado para armazenar dados dinâmicos. Simplificando, uma memória heap é alocada para valores de dados que podem mudar ao longo do ciclo de vida do programa. A pilha é uma área da memória menos organizada quando comparada à pilha.

O que é propriedade?

Cada valor em Rust tem uma variável que é chamada ownerdo valor. Cada dado armazenado no Rust terá um proprietário associado a ele. Por exemplo, na sintaxe - seja idade = 30, idade é o dono do valor 30 .

  • Cada dado pode ter apenas um proprietário por vez.

  • Duas variáveis ​​não podem apontar para o mesmo local de memória. As variáveis ​​sempre estarão apontando para diferentes locais de memória.

Transferência de propriedade

A propriedade do valor pode ser transferida por -

  • Atribuindo o valor de uma variável a outra variável.

  • Passando valor para uma função.

  • Retornando valor de uma função.

Atribuindo valor de uma variável a outra variável

O principal argumento de venda do Rust como linguagem é a segurança da memória. A segurança da memória é alcançada por meio de um controle rígido sobre quem pode usar o quê e quando as restrições.

Considere o seguinte snippet -

fn main(){
   let v = vec![1,2,3]; 
   // vector v owns the object in heap

   //only a single variable owns the heap memory at any given time
   let v2 = v; 
   // here two variables owns heap value,
   //two pointers to the same content is not allowed in rust

   //Rust is very smart in terms of memory access ,so it detects a race condition
   //as two variables point to same heap

   println!("{:?}",v);
}

O exemplo acima declara um vetor v. A ideia de propriedade é que apenas uma variável se liga a um recurso, v liga-se ao recurso ou v2liga-se ao recurso. O exemplo acima gera um erro - uso do valor movido: `v` . Isso ocorre porque a propriedade do recurso é transferida para a v2. Isso significa que a propriedade é movida de v para v2 (v2 = v) ev é invalidada após a mudança.

Passando valor para uma função

A propriedade de um valor também muda quando passamos um objeto no heap para um encerramento ou função.

fn main(){
   let v = vec![1,2,3];     // vector v owns the object in heap
   let v2 = v;              // moves ownership to v2
   display(v2);             // v2 is moved to display and v2 is invalidated
   println!("In main {:?}",v2);    //v2 is No longer usable here
}
fn display(v:Vec<i32>){
   println!("inside display {:?}",v);
}

Retornando valor de uma função

A propriedade passada para a função será invalidada quando a execução da função for concluída. Uma solução alternativa para isso é permitir que a função retorne o objeto pertencente ao chamador.

fn main(){
   let v = vec![1,2,3];       // vector v owns the object in heap
   let v2 = v;                // moves ownership to v2
   let v2_return = display(v2);    
   println!("In main {:?}",v2_return);
}
fn display(v:Vec<i32>)->Vec<i32> { 
   // returning same vector
   println!("inside display {:?}",v);
}

Propriedade e tipos primitivos

No caso de tipos primitivos, o conteúdo de uma variável é copiado para outra. Portanto, não há movimentação de propriedade acontecendo. Isso ocorre porque uma variável primitiva precisa de menos recursos do que um objeto. Considere o seguinte exemplo -

fn main(){
   let u1 = 10;
   let u2 = u1;  // u1 value copied(not moved) to u2

   println!("u1 = {}",u1);
}

A saída será - 10.