fixing ownership issues done, may have to come back
This commit is contained in:
parent
84a954a0ca
commit
aa3e08fcfb
7
ch4/fixing_ownership_issues/Cargo.lock
generated
Normal file
7
ch4/fixing_ownership_issues/Cargo.lock
generated
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fixing_ownership_issues"
|
||||||
|
version = "0.1.0"
|
6
ch4/fixing_ownership_issues/Cargo.toml
Normal file
6
ch4/fixing_ownership_issues/Cargo.toml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
[package]
|
||||||
|
name = "fixing_ownership_issues"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
113
ch4/fixing_ownership_issues/src/main.rs
Normal file
113
ch4/fixing_ownership_issues/src/main.rs
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
// This section covers some common ownership errors.
|
||||||
|
// I'll probably have to come back to this section. I'm not enjoying
|
||||||
|
// this part of Rust so learning this is not my favorite.
|
||||||
|
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// fixing an unsafe program: not enough permissions
|
||||||
|
|
||||||
|
let name = vec![String::from("Ferris!")];
|
||||||
|
let first = &name[0];
|
||||||
|
stringify_name_with_title(&name);
|
||||||
|
println!("{}", first);
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// fixing an unsafe program: copying vs. moving out of a collection
|
||||||
|
|
||||||
|
let v: Vec<i32> = vec![0, 1, 2];
|
||||||
|
let n_ref: &i32 = &v[0];
|
||||||
|
let n: i32 = *n_ref;
|
||||||
|
|
||||||
|
// If a value does not own head data, then it can be copied without a move
|
||||||
|
// Unlike what's happening below
|
||||||
|
// i32 doesn't own head data, so it can be copied without a move
|
||||||
|
// String does own heap data, so it can't be copied without a move
|
||||||
|
// &String doesn't own heap data, so it can be copied without a move
|
||||||
|
// Solution 1: Avoid taking ownership with immutable reference
|
||||||
|
let vs: Vec<String> = vec![String::from("Hello world")];
|
||||||
|
let s_ref: &String = &vs[0];
|
||||||
|
// let s: String = *s_ref;
|
||||||
|
println!("{s_ref}");
|
||||||
|
// Solution 2: Clone the data if want ownership
|
||||||
|
// Solution 3: Use Vec::remove to move string out of the vector
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// fixing an safe program: mutating different tuple fields
|
||||||
|
|
||||||
|
let mut name = (String::from("Ferris"), String::from("Rustacean"));
|
||||||
|
let first = &name.0;
|
||||||
|
name.1.push_str(", Esq.");
|
||||||
|
println!("{first} {}", name.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// fixing an unsafe program: returing a reference to the stack
|
||||||
|
// fn return_a_string() -> &String {
|
||||||
|
// let s = String::from("Hello World");
|
||||||
|
// &s
|
||||||
|
// fails because this function will get allocated but s is owned by this function.
|
||||||
|
// }
|
||||||
|
|
||||||
|
fn return_a_string_diff_owner() -> String {
|
||||||
|
let s = String::from("Hello world");
|
||||||
|
s
|
||||||
|
}
|
||||||
|
|
||||||
|
// static means it lives forever
|
||||||
|
fn return_a_string_static() -> &'static str {
|
||||||
|
"Hello world"
|
||||||
|
}
|
||||||
|
|
||||||
|
// rc is a reference-counted pointer. More in ch14
|
||||||
|
// only clones a pointer to s and not the data itself
|
||||||
|
fn return_a_string_rc() -> Rc<String> {
|
||||||
|
let s = Rc::new(String::from("Hello world"));
|
||||||
|
Rc::clone(&s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// caller provides a slot with a mutable reference
|
||||||
|
fn return_a_string_slot(output: &mut String) {
|
||||||
|
output.replace_range(.., "Hello world");
|
||||||
|
}
|
||||||
|
|
||||||
|
// fixing an unsafe program: not enough permissions
|
||||||
|
// Replace "&Vec<String>" with "$mut Vec<String>". THIS IS NOT A GOOD SOLUTION!
|
||||||
|
// Functions shouldn't mutate their inputs if the caller would not expect it.
|
||||||
|
// Basically just don't use mut in functions. Make a copy of the variable instead
|
||||||
|
// if mutating it.
|
||||||
|
fn stringify_name_with_title(name: &Vec<String>) -> String {
|
||||||
|
let mut name_clone = name.clone();
|
||||||
|
name_clone.push(String::from("Esq."));
|
||||||
|
let full = name_clone.join(" ");
|
||||||
|
full
|
||||||
|
}
|
||||||
|
|
||||||
|
fn stringify_name_with_title_final(name: &Vec<String>) -> String {
|
||||||
|
let mut full = name.join(" ");
|
||||||
|
full.push_str(" Esq.");
|
||||||
|
full
|
||||||
|
}
|
||||||
|
|
||||||
|
// fixing an unsafe program: aliasing and mutating a data structure
|
||||||
|
// This function fails
|
||||||
|
// fn add_big_strings(dst: &mut Vec<String>, src: &[String]) {
|
||||||
|
// let largest: &String = dst.iter().max_by_key(|s| s.len()).unwrap();
|
||||||
|
// for s in src {
|
||||||
|
// if s.len() > largest.len() {
|
||||||
|
// dst.push(s.clone());
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// The fix for above since we only need the length
|
||||||
|
// Shortens the lifetime of borrows on dst to not overlap with
|
||||||
|
// mutation to dst.
|
||||||
|
fn add_big_strings(dst: &mut Vec<String>, src: &[String]) {
|
||||||
|
let largest_len: usize = dst.iter().max_by_key(|s| s.len()).unwrap().len();
|
||||||
|
for s in src {
|
||||||
|
if s.len() > largest_len {
|
||||||
|
dst.push(s.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user