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.