Lecture 04 2022
Lecture 04 2022
CS110L
Jan 12, 2022
Logistics
● Solutions for week 1 exercises released! Give ‘em a read & put questions in Slack.
● Week 2 exercises will be released today and will be due Tuesday
○ Handout is on the website.
○ You should have gotten an invitation from CS110L to join a repository on GitHub. It will
be called `week2-yourSUNetID`.
■ Starter code is here; submit by pushing to this repo.
○ Please check that you got this, and let me know if you didn’t!
■ If you didn’t fill out the intro form, you don’t have a repo. Fill out the form & let me
know on Slack.
■ If you’re not officially enrolled, you don’t have a repo. Message me on Slack & I’ll
get you one.
● Reminder: no class on Monday; remote on Wednesday.
Today: more ownership & Rust!
Previously on 110L...
Ownership (From The Rust Book!)
Ownership (from Monday)
let julio = Bear::get();
let ryan = julio;
julio;
ryan;
Function calls transfer ownership (from Monday)
fn my_cool_bear_function(/* parameter */ ) {
// Do stuff
// Value (bear) will go out of scope — freed!
}
fn main() {
let julio = Bear::get();
my_cool_bear_function(julio);
/* ^This transfers ownership to parameter in function */
STACK HEAP
length = 10 'H'
capacity = 10 'I'
data = ','
'f'
julio
Ownership in Memory
let julio = "Hi,friends".to_string();
STACK let ryan = julio;
length = 10 HEAP
data = 'I'
','
length = 10
'f'
ryan capacity = 10
data = This is known as a shallow copy. The contents of the stack
is copied for the new variable. The heap contents is not.
Ownership in Memory
let julio = "Hi,friends".to_string();
STACK let ryan = julio;
length = 10 HEAP
data = 'I'
','
length = 10
'f'
ryan capacity = 10
data = What might happen if we didn't stop 'julio' from accessing the values in
its copy of the string object?
Ownership in Memory
● When we reach the end of a
scope (designated by curly- fn main() {
let julio = "Hi,friends".to_string();
braces), the Drop function is
let ryan = julio;
called.
}
● You can think of this being a
special function to properly free()
the entire object (maybe multiple
End of variable scope!
pointers to free, so the function Drop function called for
will have that implementation) variables owning values
● Similar to the destructor in C++
● Types with the Rust Drop trait
have a Drop function to call
(more on traits soon!)
Ownership in Memory
let julio = "Hi,friends".to_string();
STACK let ryan = julio;
length = 10 HEAP
data = 'I'
💣
','
length = 10
'f'
ryan capacity = 10
What might happen if we didn't stop 'julio' from accessing the values in
data = its copy of the string object? DOUBLE FREE D: D: D:
Ownership in Memory: Recap
ryan;
julio;
STACK HEAP
?
julio
?
value = 10
?
?
Ownership in Memory
?
julio value = 10
?
?
ryan value = 10 ?
What might happen if we don’t stop 'julio' from accessing the values in
its copy of the number object?
Ownership in Memory
?
julio value = 10
?
?
ryan value = 10 ?
● Some values in Rust do not make use of the heap, and are stored
directly on the stack. (integer types (u32), booleans, etc…)
○ For these types, a “shallow copy” = a full copy
● Objects that only require stack space are typically copied by default
when assigning variables
○ Types with this property have the Copy trait.
■ Instead of transferring ownership, ‘=‘ operator for assignment
(e.g., `let ryan = julio`) will create a copy
● If you have the Copy trait, Rust won’t let you implement a Drop trait
(why?)
Copy Trait Error
julio; my_cool_bear_function;
fn append_to_vector(lst: &Vec<u32>) {
lst.push(3);
}
fn main() {
let mut lst = vec![1,2,3];
append_to_vector(&lst);
}
fn main() {
let mut lst = vec![1,2,3];
append_to_vector(&mut lst);
}
let pink_shirt = &bear; let blue_shirt = &bear; let evil_patrick = &mut bear;
Borrowing + References: The Catch
let pink_shirt = &bear; let blue_shirt = &bear; let evil_patrick = &mut bear;
References Rules
&bear
&bear
&bear
OR &mut bear
&bear
References Rules
&bear
&bear
&bear
OR &mut bear
&bear
orig. var
(immut.)
Code Example
Iterator Invalidation Avoided!
fn main() {
let mut v = vec![1, 2, 3];
/* This for loop borrows the vector above to do its work. */
for i in &mut v {
println!("{}", i);
v.push(34); /* can cause resize -> moving in memory! */
} New Buffer
}
v
Old buffer 1
i 1 2
2 3
3 34
References Recap [End]
● With the ownership and borrowing rules, many different kinds of
memory errors are avoided :D
● But they do lead to trickier code to write - the Rust compiler will fight
with you as you write these programs
● Take it slow, ask questions in the #questions channel!