rust string

This type is allocated on the heap and as such is able to store an amount of text that is unknown to us at compile time.

#![allow(unused_variables)]
fn main() {
let s = String::from("hello");
}
#![allow(unused_variables)]
fn main() {
let mut s = String::from("hello");

s.push_str(", world!"); // push_str() appends a literal to a String

println!("{}", s); // This will print `hello, world!`
}

release memory


#![allow(unused_variables)]
fn main() {
{
let s = String::from("hello"); // s is valid from this point forward

// do stuff with s
} // this scope is now over, and s is no
// longer valid
}

There is a natural point at which we can return the memory our String needs to the operating system: when s goes out of scope. When a variable goes out of scope, Rust calls a special function for us. This function is called drop, and it’s where the author of String can put the code to return the memory. Rust calls drop automatically at the closing curly bracket.

#![allow(unused_variables)]
fn main() {
let s1 = String::from("hello");
let s2 = s1; //Rust considers s1 to no longer be valid
}
6898585a.png 130473ca.png

actually is a move operation
7e400833.png

deep copy use clone

#![allow(unused_variables)]
fn main() {
let s1 = String::from("hello");
let s2 = s1.clone();

println!("s1 = {}, s2 = {}", s1, s2);
}

return value and scope

fn main() {
let s1 = gives_ownership(); // gives_ownership moves its return
// value into s1

let s2 = String::from("hello"); // s2 comes into scope

let s3 = takes_and_gives_back(s2); // s2 is moved into
// takes_and_gives_back, which also
// moves its return value into s3
} // Here, s3 goes out of scope and is dropped. s2 goes out of scope but was
// moved, so nothing happens. s1 goes out of scope and is dropped.

fn gives_ownership() -> String { // gives_ownership will move its
// return value into the function
// that calls it

let some_string = String::from("hello"); // some_string comes into scope

some_string // some_string is returned and
// moves out to the calling
// function
}

// takes_and_gives_back will take a String and return one
fn takes_and_gives_back(a_string: String) -> String { // a_string comes into
// scope

a_string // a_string is returned and moves out to the calling function
}

return multiple value use tuple

fn main() {
let s1 = String::from("hello");

let (s2, len) = calculate_length(s1);

println!("The length of '{}' is {}.", s2, len);
}

fn calculate_length(s: String) -> (String, usize) {
let length = s.len(); // len() returns the length of a String

(s, length)
}

slice

#![allow(unused_variables)]
fn main() {
let s = String::from("hello world");

let hello = &s[0..5];
let world = &s[6..11];
}

The start..end syntax is a range that begins at start and continues up to, but not including, end. If we wanted to include end, we can use ..= instead of ..:

#![allow(unused_variables)]
fn main() {
let s = String::from("hello world");

let hello = &s[0..=4];
let world = &s[6..=10];
}