Rust 中的数据类型
类型 | 描述 | 值(样例) |
---|---|---|
i8, i16, i32, i64, u8, u16, u32, u64 |
确定字节的有符号或者无符号整数 | 42, -5i8, 0x400u16, 0o100i16, 20_922_789_888_000u64, b’*’ (u8 byte literal) |
isize, usize | 与机器地址长度相同(32 or 64 bits)的有符号或者无符号整数 | 137, -0b0101_0010isize, 0xffff_fc00usize |
f32, f64 | IEEE 浮点数, 单精度和双精度 | 1.61803, 3.14f32, 6.0221e23f64 |
bool | Boolean | true, false |
char | Unicode character, 32 bits wide | ‘*’, ‘\n’, ‘字’, ‘\x7f’, ‘\u{CA0}’ |
(char, u8, i32) | 元组: 允许类型混合 | (‘%’, 0x7f, -1) |
() | “unit” (empty) tuple | () |
struct S { x: f32, y: f32 } | Named-field struct | S { x: 120.0, y: 209.0 } |
struct T(i32, char); | Tuple-like struct | T(120, ‘X’) |
struct E; | Unit-like struct; has no fields | E |
enum Attend{ OnTime,Late(u32) } | Enumeration, algebraic data type | Attend::Late(5), Attend::OnTime |
Box<Attend> |
Box: owning pointer to value in heap | Box::new(Late(15)) |
&i32, &mut i32 | Shared and mutable references: nonowning pointers that must not outlive their referent | &s.y, &mut v |
String | UTF-8 string, dynamically sized | “ラーメン: ramen”.to_string() |
&str | Reference to str: nonowning pointer to UTF-8 text | “そば: soba”, &s[0..12] |
[f64; 4], [u8; 256] | Array, fixed length; elements all of same type | [1.0, 0.0, 0.0, 1.0], [b’ ‘; 256] |
Vec |
Vector, varying length; elements all of same type | vec![0.367, 2.718, 7.389] |
&[u8], &mut [u8] | Reference to slice: reference to a portion of an array or vector, comprising pointer and length | &v[10..20], &mut a[..] |
Option<&str> | Optional value: either None (absent) or Some(v) (present, with value v) | Some(“Dr.”), None |
Result |
Result of operation that may fail: either a success value Ok(v), or an error Err(e) | Ok(4096), Err(Error::last_os_error()) |
&Any, &mut Read | Trait object: reference to any value that implements a given set of methods | value as &Any, &mut file as &mut Read |
fn(&str, usize) -> isize | Pointer to function | i32::saturating_add |
(Closure types have no written form) | Closure | |a, b| { a*a + b*b } |
基本类型
1 | let v: Vec<f64> = vec![0.0, 0.707, 1.0, 0.707] |
1 | let noodles = "noodles".to_string(); |
所有权和所有权转移
所有权
C++ 中的字符串
1 | std::string s = "frayed knot"; |
Rust 中的字符串
1 | fn print_padovan() { |
Box
1 | { |
树形的所有权
1 | struct Person { name: String, birth: i32 } |
所有权转移
指针赋值
Python
1
2
3s = ['udon', 'ramen', 'soba']
t = s
u = s
当进行赋值时, 会出现什么
这三个指针将会指向同一块内存地址C++
1
2
3
4using namespace std;
vector<string> s = { "udon", "ramen", "soba" };
vector<string> t = s;
vector<string> u = s;C++ 会将这些数据都进行拷贝
Rust
1
2
3let s = vec!["udon".to_string(), "ramen".to_string(), "soba".to_string()];
let t = s;
let u = s;Rust 中, 赋值会导致所有权的转移
因为所有权转移了, s 不再持有数据, 编译器将在let u = s;
抛出错误.1
2
3
4
5
6
7
8error[E0382]: use of moved value: `s`
--> ownership_double_move.rs:9:9
|
8 | let t = s;
| - value moved here
9 | let u = s;
| ^ value used here after move
|如果你是需要副本, 可以显式的进行复制
1
2
3let s = vec!["udon".to_string(), "ramen".to_string(), "soba".to_string()];
let t = s.clone();
let u = s.clone();
所有权在类型内外之间转移
假设你现在运行这些代码1
2
3let mut noodles = vec!["udon".to_string()];
let soba = "soba".to_string();
let last;1
noodles.push(soba)
当你执行上面的代码之后, soba
的所有权将会转移到 noodles
中.1
last = noodles.pop().unwrap();
而当你执行以上的代码后, 字符串的所有权又将交给 last
移动所有权的例外 — 可复制的类型
1 | let str1 = "somnambulance".to_string(); |
共享的所有权
1 | use std::rc::Rc; |
但是共享所有权可能会带来循环引用的问题, 引起内存泄漏
引用
可以使一个变量改变自己的指向1
2
3
4
5let x = 10;
let y = 20;
let mut r = &x;
if b { r = &y; }
assert!(*r == 10 || *r == 20);
引用可以指向引用1
2
3
4
5struct Point { x: i32, y: i32 }
let point = Point { x: 1000, y: 729 };
let r: &Point = &point;
let rr: &&Point = &r;
let rrr: &&&Point = &rr;
引用的生命周期不能超过被引用数据的生命周期
1 | let v = vec![4, 8, 19, 27, 34, 10]; |
1
2
3
4
5
6
7error[E0505]: cannot move out of `v` because it is borrowed
--> references_sharing_vs_mutation_1.rs:10:9
|
9 | let r = &v;
| - borrow of `v` occurs here
10 | let aside = v; // move vector to aside
| ^^^^^ move out of `v` occurs here1
2
3
4
5
6let v = vec![4, 8, 19, 27, 34, 10];
{
let r = &v;
r[0]; // ok: vector is still there
}
let aside = v;
1 | fn extend(vec: &mut Vec<f64>, slice: &[f64]) { |
答案是不行, 因为当数组的长度扩展之后, 应该是指向新分配的内存, 但是旧的引用还是指向旧的内存地址. 这不仅仅是Rust 会出现的问题.
不过 Rust 会在编译时阻止你这样做1
2
3
4
5
6
7
8error[E0502]: cannot borrow `wave` as immutable because it is also borrowed as mutable
--> references_sharing_vs_mutation_2.rs:9:24
|
9 | extend(&mut wave, &wave);
| ---- ^^^^- mutable borrow ends here
| | |
| | immutable borrow occurs here
|
1 | // Paring these principles down to the simplest possible examples: |
Trait Object
Unsized Type
Closure
Closure Type
• Fn is the family of closures and functions that you can call multiple times without restriction. This highest category also includes all fn functions.
• FnMut is the family of closures that can be called multiple times if the closure itself is declared mut.
• FnOnce is the family of closures that can be called once, if the caller owns the closure.