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