Propiedad
## Objetivos de Aprendizaje
- Comprender las reglas de propiedad de Rust
- Dominar el prestamo con referencias
- Aprender los fundamentos de tiempos de vida
- Evitar errores comunes de propiedad
## Que es la Propiedad?
La propiedad es el sistema unico de Rust para gestionar la memoria. Cada valor tiene un solo propietario, y cuando el propietario sale del alcance, el valor se descarta.
## Reglas de Propiedad
1. Cada valor tiene exactamente un propietario
2. Solo puede haber un propietario a la vez
3. Cuando el propietario sale del alcance, el valor se descarta
```rust
fn main() {
let s1 = String::from("hello"); // s1 es el propietario del string
let s2 = s1; // La propiedad se mueve a s2
// println!("{}", s1); // Error: s1 ya no es valido
println!("{}", s2); // OK: s2 es el propietario del valor
}
```
## Semantica de Movimiento
### Strings vs Literales
```rust
// String (alojado en heap) - SE MUEVE
let s1 = String::from("hello");
let s2 = s1; // s1 se mueve a s2
// s1 ya no es valido
// Literales de string (&str) - SE COPIAN (Trait Clone)
let s1 = "hello";
let s2 = s1; // s1 se copia a s2
println!("{} {}", s1, s2); // Ambos son validos
```
### Tipos Enteros - Siempre se Copian
```rust
let x = 5;
let y = x; // Copia (i32 implementa Copy)
println!("{} {}", x, y); // Ambos son validos
```
## Clone y Copy
### Clone (Copia Profunda)
```rust
let s1 = String::from("hello");
let s2 = s1.clone(); // Copia profunda de datos del heap
println!("{} {}", s1, s2); // Ambos son validos
```
### Trait Copy (Datos de Pila)
```rust
// Tipos que implementan Copy (solo pila):
// - Todos los tipos enteros
// - Todos los tipos de punto flotante
// - Booleano
// - Caracter
// - Tupla de tipos Copy
// - Arreglo de tipos Copy
let x = (1, 2, 3);
let y = x; // Copia, ambos validos
```
## Propiedad y Funciones
### Pasar Valores a Funciones
```rust
fn main() {
let s = String::from("hello");
takes_ownership(s); // El valor de s se mueve a la funcion
// println!("{}", s); // Error: s ya no es valido
let x = 5;
makes_copy(x); // x se copia (i32 es Copy)
println!("{}", x); // OK: x sigue siendo valido
}
fn takes_ownership(s: String) {
println!("{}", s);
} // s se descarta aqui
fn makes_copy(x: i32) {
println!("{}", x);
} // x se descarta aqui
```
### Valores de Retorno y Alcance
```rust
fn main() {
let s1 = gives_ownership(); // La funcion devuelve la propiedad
let s2 = String::from("hello");
let s3 = takes_and_returns(s2); // s2 se mueve adentro, s3 se devuelve
}
fn gives_ownership() -> String {
let s = String::from("hello");
s // Devuelve y mueve al llamador
}
fn takes_and_returns(s: String) -> String {
s // Devuelve y mueve al llamador
}
```
## Prestamo
### Referencias
Una referencia te permite acceder a un valor sin tomar la propiedad.
```rust
fn main() {
let s1 = String::from("hello");
let len = calculate_length(&s1); // Pasa referencia a s1
println!("{} has length {}", s1, len); // s1 sigue siendo valido
}
fn calculate_length(s: &String) -> usize {
s.len()
} // s sale del alcance, pero NO se descarta
```
### Referencias Mutables
```rust
fn main() {
let mut s = String::from("hello");
change(&mut s);
println!("{}", s);
}
fn change(s: &mut String) {
s.push_str(", world");
}
```
### Reglas de Prestamo
1. Una referencia mutable O cualquier numero de referencias inmutables
2. Las referencias siempre deben ser validas (sin referencias colgantes)
```rust
let mut s = String::from("hello");
let r1 = &s; // OK
let r2 = &s; // OK: multiples referencias inmutables
// let r3 = &mut s; // Error: no se puede prestar mutablemente mientras existen referencias inmutables
println!("{} {}", r1, r2);
// r1 y r2 ya no se usan despues de este punto
let r3 = &mut s; // OK: las referencias inmutables terminaron
r3.push_str(" world");
```
## Tiempos de Vida
### Que son los Tiempos de Vida?
Los tiempos de vida son anotaciones que ayudan al compilador a asegurar que las referencias sean validas.
```rust
fn main() {
let r;
{
let x = 5;
r = &x; // Error: x no vive lo suficiente
}
println!("{}", r);
}
```
### Anotaciones de Tiempo de Vida
```rust
// &'a significa que la referencia vive al menos tanto como el tiempo de vida 'a
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
x
} else {
y
}
}
fn main() {
let s1 = String::from("long string");
let result;
{
let s2 = String::from("xyz");
result = longest(s1.as_str(), s2.as_str());
println!("Longest: {}", result);
}
// result seria invalido aqui si se usara
}
```
### Eliminacion de Tiempos de Vida
El compilador usa reglas para inferir tiempos de vida en casos comunes:
```rust
// Estos son equivalentes:
fn first_word(s: &str) -> &str { }
fn first_word<'a>(s: &'a str) -> &'a str { }
// Regla 1: Cada parametro de referencia obtiene su propio tiempo de vida
// Regla 2: Si hay exactamente un tiempo de vida de entrada, se aplica a la salida
// Regla 3: Si hay un &self o &mut self, se aplica a la salida
```
### Tiempo de Vida Estatico
`'static` significa que la referencia vive durante todo el programa:
```rust
let s: &'static str = "I live forever";
```
Los literales de string tienen tiempo de vida `'static`.
## El Tipo Slice
Los slices son referencias a una porcion de una coleccion:
```rust
let s = String::from("hello world");
let hello = &s[0..5]; // Igual que &s[..5]
let world = &s[6..11]; // Igual que &s[6..]
// Slice de string
fn first_word(s: &str) -> &str {
let bytes = s.as_bytes();
for (i, &item) in bytes.iter().enumerate() {
if item == b' ' {
return &s[0..i];
}
}
&s[..]
}
```
## Resumen
- Cada valor tiene exactamente un propietario
- Cuando la propiedad se mueve, la variable original se invalida
- Los tipos Copy (primitivos) se copian en lugar de moverse
- Clone crea una copia profunda
- Las referencias piden prestadas valores sin tomar la propiedad
- La referencia mutable permite modificar el valor prestado
- Solo una referencia mutable O multiples referencias inmutables
- Los tiempos de vida aseguran que las referencias sean validas mientras sea necesario
- Los slices son referencias a porciones de datos
Comments
Comments powered by Giscus
To enable comments, add your Giscus embed code here.
Learn more about Giscus →