let vec1 = vec![1, 2, 3, 4];
let vec2 = vec![Box::new(1), Box::new(2), Box::new(3), Box::new(4)];
他们之间有什么区别?我已经在堆上分配了vec1,那么vec1的所有元素不也在堆上吗?为什么我还需要像在vec2中一样单独在堆上分配它们呢?let vec1 = vec![1, 2, 3, 4];
let vec2 = vec![Box::new(1), Box::new(2), Box::new(3), Box::new(4)];
他们之间有什么区别?我已经在堆上分配了vec1,那么vec1的所有元素不也在堆上吗?为什么我还需要像在vec2中一样单独在堆上分配它们呢?我将绘制一张图表。第一个值是指向堆上连续数字数组的指针。
(stack) (heap) ┌──────┐ ┌───┐ │ vec1 │──→│ 1 │ └──────┘ ├───┤ │ 2 │ ├───┤ │ 3 │ ├───┤ │ 4 │ └───┘
第二个版本添加了额外的间接性。元素仍然在堆上,但现在它们在堆的其他位置。
(stack) (heap) ┌───┐ ┌──────┐ ┌───┐ ┌─→│ 1 │ │ vec2 │──→│ │─┘ └───┘ └──────┘ ├───┤ ┌───┐ │ │───→│ 2 │ ├───┤ └───┘ │ │─┐ ┌───┐ ├───┤ └─→│ 3 │ │ │─┐ └───┘ └───┘ │ ┌───┐ └─→│ 4 │ └───┘
由于Rust中所有权的工作方式,您不会遇到任何语义差异。额外的间接性会导致更差的内存使用和缓存局部性。
vec![1, 2, 3, 4]
是由 i32
类型组成的向量。
vec![Box::new(1), Box::new(2), Box::new(3), Box::new(4)]
是由指向 i32
类型的所有权指针组成的向量。Rust 的所有权指针类似于 C++ 的 unique_ptr。
1
是值为 1 的变量,而~1
则是指向 1 的拥有所有权的指针。因此,在vec2
中,您只是获得了一个更高级别的间接引用。 - Paolo Falabella