我尝试使用以下代码:
fn main() {
let array = box [1, 2, 3];
}
,在我的程序中,它导致编译错误:error: obsolete syntax: ~[T] is no longer a type
。
AFAIU,Rust中没有动态大小数组(大小必须在编译时知道)。但是,在我的代码片段中,数组确实具有静态大小,并且应该是~[T, ..3]
类型(拥有大小为3的静态数组),而编译器说它具有类型~[T]
。是否有任何深层原因导致无法在堆上分配静态大小的数组?
P.S。是的,我听说过Vec
。
答案 0 :(得分:4)
据我所知,盒子表达是实验性的。您可以使用Box::new()
之类的代码来抑制警告。
fn main() {
let array1 = Box::new([1, 2, 3]);
// or even
let array2: Box<[i32]> = Box::new([1, 2, 3]);
}
请查看Shepmaster的评论,因为这些是不同的类型。
答案 1 :(得分:0)
既然我到了这里,其他人也可以。 Rust 一直在发展,在这个答案中,Rust 的稳定值为 1.53,夜间为 1.55。
Box::new([1, 2, 3])
是推荐的方式,它可以完成它的工作,但是有一个问题:数组是在堆栈上创建的,然后复制到堆中。这是 Box 的记录行为:
Move a value from the stack to the heap by creating a Box:
意思是,它包含一个隐藏的memcopy
,对于大数组,堆分配甚至会因堆栈溢出而失败。
const X: usize = 10_000_000;
let failing_huge_heap_array = [1; X];
thread 'main' has overflowed its stack
fatal runtime error: stack overflow
到目前为止(Rust 1.53)有几种解决方法,最直接的是创建一个向量并将向量转换为盒装切片:
const X: usize = 10_000_000;
let huge_heap_array = vec![1; X].into_boxed_slice();
这有效,但有两个小问题:它丢失了类型信息,应该是 Box<[i32; 10000000]> 现在是 Box<[usize]> 并且额外占用堆栈上的 16 个字节,而不是一个只占用 8 个字节的数组。
...
println!("{}", mem::size_of_val(&huge_heap_array);
16
没什么大不了的,但它伤害了我个人的僧侣因素。
经过进一步研究,丢弃需要每晚的选项,例如 OP box [1, 2, 3]
似乎带着功能 #![feature(box_syntax)]
和 arr 板条箱(很好但也需要每晚),这是我最好的解决方案发现在没有隐藏 memcopy
的情况下在堆上分配数组
是 Simias
/// A macro similar to `vec![$elem; $size]` which returns a boxed array.
///
/// ```rustc
/// let _: Box<[u8; 1024]> = box_array![0; 1024];
/// ```
macro_rules! box_array {
($val:expr ; $len:expr) => {{
// Use a generic function so that the pointer cast remains type-safe
fn vec_to_boxed_array<T>(vec: Vec<T>) -> Box<[T; $len]> {
let boxed_slice = vec.into_boxed_slice();
let ptr = ::std::boxed::Box::into_raw(boxed_slice) as *mut [T; $len];
unsafe { Box::from_raw(ptr) }
}
vec_to_boxed_array(vec![$val; $len])
}};
}
const X: usize = 10_000_000;
let huge_heap_array = box_array![1; X];
不会溢出栈,只占用8个字节,同时保留类型。
它使用 unsafe,但将其限制为一行代码。在 box [1;X]
语法出现之前,恕我直言,这是一个干净的选择。
答案 2 :(得分:-2)
写得像:
let mut buffer= vec![0; k];
它使u8数组的长度等于k。