Box
源码:
1 | use std::mem::size_of;
2 | fn main() {
3 | let local = 5i32;
4 | let boxed = Box::new(5i32);
5 | println!("size_of::<i32>() = {},size_of::<Box<i32>>() = {}", size_of::<i32>(), size_of::<Box<i32>>());
6 | let stack = &local as *const i32 as usize;
7 | let heap = &*boxed as *const i32 as usize;
8 | println!("局部 i32 的地址 {:#x}(栈),Box 里的 i32 地址 {:#x}(堆);相差 {} MiB", stack, heap, stack.abs_diff(heap) >> 20);
9 | println!("*boxed + 1 = {}(自动解引用)", *boxed + 1);
10 | }
编译:成功
运行(退出码 0):
size_of::<i32>() = 4,size_of::<Box<i32>>() = 8
局部 i32 的地址 0x16b82a704(栈),Box 里的 i32 地址 0x104d45300(堆);相差 1642 MiB
*boxed + 1 = 6(自动解引用) 源码:
1 | enum List { Cons(i32, List), Nil }
2 | fn main() {}
编译:失败
error[E0072]: recursive type `List` has infinite size
--> <实验目录>/src/u28b.rs:1:1
|
1 | enum List { Cons(i32, List), Nil }
| ^^^^^^^^^ ---- recursive without indirection
|
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
|
1 | enum List { Cons(i32, Box<List>), Nil }
| ++++ +
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0072`.
源码:
1 | use std::mem::size_of;
2 | #[allow(dead_code)]
3 | enum List { Cons(i32, Box<List>), Nil }
4 | use List::{Cons, Nil};
5 | fn sum(l: &List) -> i32 { match l { Cons(v, rest) => v + sum(rest), Nil => 0 } }
6 | fn main() {
7 | let list = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil))))));
8 | println!("sum = {},size_of::<List>() = {} 字节(i32 + Box 指针 + 标签,与链表长度无关)", sum(&list), size_of::<List>());
9 | }
编译:成功
运行(退出码 0):
sum = 6,size_of::<List>() = 16 字节(i32 + Box 指针 + 标签,与链表长度无关)链表等递归结构的更多讨论(为什么 LinkedList 通常不是首选)见LinkedList 为什么通常不是首选。
源码:
1 | use std::hint::black_box;
2 | use std::time::Instant;
3 | const N: usize = 1 << 20;
4 | fn pass_array(a: [u8; N]) -> [u8; N] { black_box(a) }
5 | fn pass_box(a: Box<[u8; N]>) -> Box<[u8; N]> { black_box(a) }
6 | fn main() {
7 | let arr = [1u8; N];
8 | let t = Instant::now(); let mut acc = 0u64;
9 | for _ in 0..200 { let x = pass_array(black_box(arr)); acc += x[0] as u64; }
10 | let t_arr = t.elapsed().as_nanos() as f64 / 200.0;
11 | let bx: Box<[u8; N]> = vec![1u8; N].into_boxed_slice().try_into().unwrap();
12 | let t = Instant::now(); let mut cur = bx;
13 | for _ in 0..200 { cur = pass_box(black_box(cur)); acc += cur[0] as u64; }
14 | let t_box = t.elapsed().as_nanos() as f64 / 200.0;
15 | black_box(acc);
16 | println!("按值传递并返回 [u8; 1 MiB]:每次约 {:.0} ns", t_arr);
17 | println!("按值传递并返回 Box<[u8; 1 MiB]>:每次约 {:.1} ns", t_box);
18 | }
编译:成功
运行(退出码 0):
按值传递并返回 [u8; 1 MiB]:每次约 61267 ns
按值传递并返回 Box<[u8; 1 MiB]>:每次约 4.4 ns计时用 release 与 black_box,数字是单次运行结果。内存布局见Box、Rc、Arc 的内存布局。
编译:成功
运行(退出码 0):
Box 存在时:alloc +1,dealloc +0
离开作用域后:alloc +1,dealloc +1