在Rust中的堆上创建固定大小的数组

时间:2014-09-12 09:35:50

标签: rust

我尝试使用以下代码:

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

3 个答案:

答案 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。