Ownership

All about Ownership in Rust


What is Ownership?

  • Data has single owner (who can manipulate this single data)
  • Immutable aliases allowed
  • Mutation only has 1 reference
  • Ownership avoids double free
  • Ownership replaces handles free() issues:
free(x)

Rules

  1. Each value has one owner (variable)
  2. Only one owner at a time
  3. In terms of memory, when owner out of scope, the value is dropped (freed)
{
	let mut s = String::from("Hello"); // stored in heap
	s.push_str(" world"); // valid since s is mutable
	println!("{}", s); // compiles :)
}
  • Since we only can have one owner, x losses ownership, y takes ownership
  • If we were to print x, does not compile (rust yell us: it's unsafe!)
{
	let x = String::from("Hello"); // stored in heap
	let y = x; // hello was move from x to y
	
	println!("{}", y) // good
	println!("{}", x); // ERROR, y is owner, cannot print Hello
}

Note: y = s is a shallow copy Note: cannot take ownership back to s ( s = y ) unless we do another let s = y

What happen here

let mut x = String::from("hello")
// x is a mutable reference to the value hello
{
	let y = &mut x;
	// y is a mutable reference to the value hello
	// we cannot have more than one mutable reference so x becomes invalid for as long as  y exists
	pritnln!("{}", y, x);
} // y goes out of scope, so now x becomes valid again
 
x.push_str("world"); // we can use 'x'
println!("{}", x)
Example:
fn main() {
	let String::from("hello"); 
	{
		let b = a; // a is moved to b
		println!("b is {}",b);
	} // a is dropped, cannot longer be accessed outside scope
	println!("a is {}",a); // ERROR
}
fn main() {
	let a = 3; // stored in stack
	{
		let b = a; // a is moved to b
		println!("b is {}",b);
	} 
	println!("a is {}",a); // compiles fine
}

Ownership in Functions

  • There are 3 ownership happening in this piece of code
{
  let s = String::from("Hello") // 1. s is owner
  let y = identity(s); // 3. x losses ownership, y is now the owner
  println!(y) // Fine
  println!(s) // Error
}
 
fn identity(x: String) -> String {
  x // pushed in the stack, s losses ownership, 2. x is now the owner
}
fn main() {
	let x = String::from("hello"); // x owns hello
	ley = funct(x);  // after funct is called, y is the owner of hello
	println!("{}", y);
}
 
fn funct(a:String) -> String {
	pritnln!("{}", a) // `a` still has ownership
	return a; // `a` is being passed back to the caller
} // returns 

How about dont want pass to pass owner -> References