RUST学习2

rust

All data stored on the stack must have a known, fixed size. Data with an unknown size at compile time or a size that might change must be stored on the heap instead.

Pushing to the stack is faster than allocating on the heap because the allocator never has to search for a place to store new data;

Ownership Rules

解决堆上数据 的问题

Each value in Rust has a variable that’s called its owner.
There can only be one owner at a time.
When the owner goes out of scope, the value will be dropped. 从堆中回收

string 存在scope中

the concept of copying the pointer, length, and capacity without copying the data probably sounds like making a shallow copy.

rust

1
2
3
4
let s1 = String::from("hello");
| -- move occurs because `s1` has type `std::string::String`, which does not implement the `Copy` trait
3 | let s2 = s1;
| -- value moved here

s1 无效 回收只s2

1
2
3
4
5
6
7
fn main() {
let s1 = String::from("hello");
let s2 = s1.clone();

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

1
2
x=5
y=x

栈中不用clone

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

fn main() {
let s = String::from("hello"); // s comes into scope

takes_ownership(s); // s's value moves into the function...
// ... and so is no longer valid here

let x = 5; // x comes into scope

makes_copy(x); // x would move into the function,
// but i32 is Copy, so it’s okay to still
// use x afterward

} // Here, x goes out of scope, then s. But because s's value was moved, nothing
// special happens.

References and Borrowing

引用 不拿所有权 也称借

1
2
3
4
5
fn main() {
let mut s = String::from("hello");

change(&mut s);
}
1
2
3
fn change(some_string: &mut String) {
some_string.push_str(", world");
}

一个可变变量只能引用一次

1
2
3
4
5
6
7
8
9
fn main() {
let mut s = String::from("hello");

{
let r1 = &mut s;
} // r1 goes out of scope here, so we can make a new reference with no problems.

let r2 = &mut s;
}

用花括号创建一个空间,来引用,

We also cannot have a mutable reference while we have an immutable one.
可变变量有不变引用后,不能创建可变引用

1
2
3
4
5
6
7
8
9
10
11
fn main() {
let mut s = String::from("hello");

let r1 = &s; // no problem
let r2 = &s; // no problem
println!("{} and {}", r1, r2);
// r1 and r2 are no longer used after this point

let r3 = &mut s; // no problem
println!("{}", r3);
}

引用范围从创建到最后一次使用
关键是不重叠

1
2
3
4
5
6
7
8
9
10
11
fn main() {
let reference_to_nothing = dangle();
}

fn dangle() -> &String { // dangle returns a reference to a String

let s = String::from("hello"); // s is a new String

&s // we return a reference to the String, s
} // Here, s goes out of scope, and is dropped. Its memory goes away.
// Danger!

slice

1
2
3
4
5
6
7
8
9
10
11
fn first_word(s: &String) -> usize {
let bytes = s.as_bytes();

for (i, &item) in bytes.iter().enumerate() {
if item == b' ' {
return i;
}
}

s.len()
}

iter is a method that returns each element in a collection
enumerate wraps the result of iter and returns each element as part of a tuple instead.
第一个参数是索引值,第二个是值的引用

1
2
3
4
5
6
fn main() {
let s = String::from("hello world");

let hello = &s[0..5]; //0可以省去
let world = &s[6..11]; 存6-10
}

string slices

1
2
3
4
5
6
7
8
fn main() {
let s = String::from("hello");

let len = s.len();

let slice = &s[3..len];
let slice = &s[3..]; //相同
}

The type that signifies “string slice” is written as &str:

1
2
3
4
5
6
7
8
9
10
11
12
fn first_word(s: &String) -> &str {
let bytes = s.as_bytes();

for (i, &item) in bytes.iter().enumerate() {
if item == b' ' {
return &s[0..i];
}
}

&s[..]
}

String Literals Are Slices
固定字符串就是一种切片
The type of s here is &str
it’s a slice pointing to that specific point of the binary

fn first_word(s: &str) -> &str {
可以接受&String 和 &str //String 和 字符串 如“hello”

1
2
3
4
5
6
fn main() {
let a = [1, 2, 3, 4, 5];

let slice = &a[1..3];
}

struct

结构体字段里都是可变的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
struct User {
username: String,
email: String,
sign_in_count: u64,
active: bool,
}

struct User {
username: String,
email: String,
sign_in_count: u64,
active: bool,
}

fn main() {
let user1 = User {
email: String::from("someone@example.com"),
username: String::from("someusername123"),
active: true,
sign_in_count: 1,
};
}

顺序随便

1
2
3
4
5
6
struct User {
username: String,
email: String,
sign_in_count: u64,
active: bool,
}
1
2
3
4
5
6
7
8
fn build_user(email: String, username: String) -> User { //返回struct 实例
User {
email: email,
username: username,
active: true,
sign_in_count: 1,
}
}
1
2
3
4
5
6
fn main() {
let user1 = build_user(
String::from("someone@example.com"),
String::from("someusername123"),
);
}
1
2
3
4
5
6
7
8
9
fn build_user(email: String, username: String) -> User {
User {
email, //省略rather than email: email.
username,
active: true,
sign_in_count: 1,
}
}

更新赋予另一实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
struct User {
username: String,
email: String,
sign_in_count: u64,
active: bool,
}

fn main() {
let user1 = User {
email: String::from("someone@example.com"),
username: String::from("someusername123"),
active: true,
sign_in_count: 1,
};

let user2 = User {
email: String::from("another@example.com"),
username: String::from("anotherusername567"),
..user1 // .. specifies that the remaining fields not explicitly set should have the same value as the fields in the given instance.
};
}

tuple struct

1
2
3
4
5
6
7
8
fn main() {
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);

let black = Color(0, 0, 0);
let origin = Point(0, 0, 0);
}

做网站
文件路径的一些通用规则:

若引用的目标文件与 HTML 文件同级,只需直接使用文件名,比如 my-image.jpg
要引用子文件夹中的文件,要在路径前写下目录名并加一个斜杠,比如 subdirectory/my-image.jpg
若引用的目标文件位于 HTML 文件的上级,需要加上两个点。比如,如果 index.html 在 test-site 下面的一个子目录而 my-image.png 在 test-site 目录,你可以在 index.html 里使用 ../my-image.png 引用 my-image.png
以上方法可以随意组合,比如 ../subdirectory/another-subdirectory/my-image.png。