Lesson 1
Ownership and moves
Understand what happens when you assign, pass, or return values in Rust.
Why ownership exists
A String allocates a buffer on the heap. That buffer must be released exactly
once: failing to release it wastes memory; releasing it twice or too early can
make the program access memory that is no longer valid.
Rust prevents that problem without a garbage collector and without requiring
manual calls to free. Every value has a single owner and, when that owner goes
out of scope, Rust runs drop and releases its associated resources.
That is why let s2 = s1; does not duplicate a String buffer: it transfers
ownership to s2 and invalidates s1. This is a move. Copy types are
duplicated implicitly; clone creates an explicit duplicate, while a reference
lets code use the value temporarily without becoming its owner.
What changes compared with other languages
The same assignment does not express the same operation in every language. If
a provides access to a value backed by dynamically allocated memory, the usual
behavior is:
| Language | When b = a runs |
Releasing the resource |
|---|---|---|
| TypeScript / Java | A managed reference is copied. Both a and b provide access to the same object. |
The garbage collector acts after the object becomes unreachable. |
| C++ | A type such as std::string is copied. A move may be enabled with b = std::move(a); afterwards, a remains valid but its state may have changed. |
Each object releases its resources from its destructor through RAII; direct use of delete is normally unnecessary. |
| Rust | A type such as String is moved: b receives the value and a can no longer be used. Duplicating the buffer requires an explicit a.clone(). |
The resource is released through drop when its current owner leaves scope. |
Rust does allow multiple shared references, &T. In safe code, borrowing
prevents mutable access from overlapping with any other access to the same value:
there may be several shared references or one mutable reference, but not both at
the same time. The compiler checks this rule and also ensures that no reference
outlives the value it points to.
Exercise 01 · Ownership
Complete two functions without consuming their input values.
Both functions only need to read their arguments. Accept them by reference, complete the code, and run the tests.
Objective
Implement saludo_mas_largo to return one of the texts received by reference. Implement crear_saludo to create a new String without consuming the input argument.
Implement
Complete one function in each editor.
Function 01
Select the longest text
Accept two &str values and return the longest one.
/// Devuelve el saludo más largo sin tomar la propiedad.
pub fn saludo_mas_largo(a: String, b: String) -> String {
todo!("devuelve a o b")
}Function 02
Build a new String
Accept an &str and create a greeting without consuming the input value.
/// Construye un saludo nuevo sin consumir el nombre.
pub fn crear_saludo(nombre: String) -> String {
todo!("construye un String nuevo")
}Check
Run the tests and correct the code using the Rust diagnostic.
Visible tests
Modify the code before running the tests.
Help
View a hint or compare your implementation with the solution.
/// Devuelve el saludo más largo sin quedarse con la propiedad
/// de ninguno de los dos: solo pide prestado.
#[must_use]
pub fn saludo_mas_largo<'a>(a: &'a str, b: &'a str) -> &'a str {
if a.len() >= b.len() { a } else { b }
}
/// Crea un saludo propio a partir de un nombre prestado.
#[must_use]
pub fn crear_saludo(nombre: &str) -> String {
let mut saludo = String::from("hola, ");
saludo.push_str(nombre);
saludo
}
// Playground entry point for this example.
fn main() {
let corto = "hey";
let largo = "buenas tardes";
println!("{}", saludo_mas_largo(corto, largo));
println!("{}", crear_saludo("rusticiero"));
}Summary
- Every value has a single owner; when it leaves scope, the value is freed automatically.
- Assigning or passing a value with heap data moves ownership; the previous variable becomes invalid.
clone()creates an explicit deep copy when you truly need two owners.Copytypes (no heap) are copied on assignment and both variables stay alive.- The compiler turns memory errors into compile errors with actionable messages.