Rust - Propiedad

La memoria para un programa se puede asignar de la siguiente manera:

  • Stack
  • Heap

Apilar

Una pila sigue a un último en entrar, primero en salir. Stack almacena valores de datos cuyo tamaño se conoce en tiempo de compilación. Por ejemplo, una variable de tamaño fijo i32 es candidata para la asignación de pila. Su tamaño se conoce en tiempo de compilación. Todos los tipos escalares se pueden almacenar en la pila ya que el tamaño es fijo.

Considere un ejemplo de una cadena, a la que se le asigna un valor en tiempo de ejecución. El tamaño exacto de dicha cadena no se puede determinar en tiempo de compilación. Por lo tanto, no es un candidato para la asignación de pila sino para la asignación de pila.

Montón

La memoria de pila almacena valores de datos cuyo tamaño se desconoce en el momento de la compilación. Se utiliza para almacenar datos dinámicos. En pocas palabras, se asigna una memoria dinámica a valores de datos que pueden cambiar a lo largo del ciclo de vida del programa. El montón es un área de la memoria que está menos organizada en comparación con la pila.

¿Qué es la propiedad?

Cada valor en Rust tiene una variable que se llama ownerdel valor. Todos los datos almacenados en Rust tendrán un propietario asociado. Por ejemplo, en la sintaxis, sea ​​age = 30, age es el propietario del valor 30 .

  • Cada dato puede tener solo un propietario a la vez.

  • Dos variables no pueden apuntar a la misma ubicación de memoria. Las variables siempre apuntarán a diferentes ubicaciones de memoria.

Transferencia de propiedad

La propiedad del valor puede ser transferida por:

  • Asignar valor de una variable a otra variable.

  • Pasar valor a una función.

  • Devolver valor de una función.

Asignar valor de una variable a otra variable

El punto clave de venta de Rust como lenguaje es la seguridad de su memoria. La seguridad de la memoria se logra mediante un control estricto sobre quién puede usar qué y cuándo las restricciones.

Considere el siguiente fragmento:

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);
}

El ejemplo anterior declara un vector v. La idea de propiedad es que solo una variable se une a un recurso, ya sea v se une al recurso o v2se une al recurso. El ejemplo anterior arroja un error: uso del valor movido: `v` . Esto se debe a que la propiedad del recurso se transfiere a v2. Significa que la propiedad se mueve de v a v2 (v2 = v) y v se invalida después del movimiento.

Pasar valor a una función

La propiedad de un valor también cambia cuando pasamos un objeto en el montón a un cierre o función.

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);
}

Devolver valor de una función

La propiedad pasada a la función se invalidará cuando se complete la ejecución de la función. Una solución para esto es dejar que la función devuelva el objeto de propiedad al llamador.

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);
}

Propiedad y tipos primitivos

En el caso de tipos primitivos, el contenido de una variable se copia en otra. Por lo tanto, no se está produciendo ningún movimiento de propiedad. Esto se debe a que una variable primitiva necesita menos recursos que un objeto. Considere el siguiente ejemplo:

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

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

La salida será - 10.