如何在Rust中动态分配数组?

10

一旦我分配了数组,如何手动释放它?在不安全模式下是否可以进行指针算术运算?

就像在 C++ 中:


double *A=new double[1000];
double *p=A;
int i;
for(i=0; i<1000; i++)
{
     *p=(double)i;
      p++;
}
delete[] A;

在Rust中是否有相应的代码?

1
这里的数组部分(http://rustbyexample.com/primitives/array.html)可能会对您有所帮助。 - hurnhu
8
我想指出这是可怕的C++代码(存在delete就是一个提示)。符合惯用法的C++应该是std::vector<double> A; for (int i = 0; i < 1000; ++i) { A.push_back(i); }:没有显式的内存操作! - Matthieu M.
2个回答

19

如果您还没有这样做,基于您的问题,我建议阅读Rust Book。习惯用语的 Rust 几乎永远不会涉及手动释放内存。

至于相当于动态数组的东西,您需要 一个向量。除非您在进行一些不寻常的操作,否则应避免在 Rust 中使用指针算术运算。您可以将上面的代码各种方式写成:

// Pre-allocate space, then fill it.
let mut a = Vec::with_capacity(1000);
for i in 0..1000 {
    a.push(i as f64);
}

// Allocate and initialise, then overwrite
let mut a = vec![0.0f64; 1000];
for i in 0..1000 {
    a[i] = i as f64;
}

// Construct directly from iterator.
let a: Vec<f64> = (0..1000).map(|n| n as f64).collect();

16
题目要求提供一个数组,并给出 C++ 的等价示例,而这个答案则涵盖了动态集合类型。这也扩展到了在 Rust 中分配数组的前两个 Google 搜索结果,但我认为这并没有回答问题。 - Score_Under
3
除了C++代码使用动态分配数组之外,实际上几乎没有任何实际差别。直译不安全且不符惯用语。另外,考虑到原始提问者接受了给出的答案,我认为它确实回答了他们想要询问的问题。 - DK.
3
问题中的数组是在运行时分配的,但除此之外,它是一个固定的数组(无法调整大小、追加等)。Rust确实有一个相应的类型,并且在某些标准库函数中是必需的(例如从文件中批量读取时)。 - Score_Under
1
@Score_Under:通常情况下,Rust没有一种可靠地在堆上分配固定大小数组的方法,除非通过Vec进行,此时沉迷于仅具有利基用途的类型并没有太多好处。另外,在问题中没有表明使用固定大小的重要性。至于标准库是否需要固定大小的数组,您将不得不指定,因为我不知道任何相关信息。 - DK.
请点击以下链接查看有关read方法的文档:https://doc.rust-lang.org/std/io/trait.Read.html#tymethod.read。该方法用于对文件进行部分读取,需要一个u8数组作为参数,而不接受u8向量。如果想要使用向量作为参数并指定要读取的数据量,可以使用等效的`read_to_end`方法。 - Score_Under
2
@Score_Under 在你所提到的函数中,fn read(&mut self, buf: &mut [u8]) -> Result<usize>中的buf是一个切片而不是数组。 - Taras Alenin

16

完全可以在堆上分配固定大小的数组:

let a = Box::new([0.0f64; 1000]);
由于解引用强制转换,你仍然可以将此作为数组使用:
for i in 0..1000 {
    a[i] = i as f64;
}

您可以手动释放它,方法如下:

std::mem::drop(a);

drop 接管数组的所有权,因此这完全安全。如其他答案所述,几乎永远不需要这样做,当变量超出作用域时,Box 将自动释放。


1
这不会在堆栈上分配空间,然后再传递到堆上吗?因为对于非常大的数组(比如90kb),这种方法行不通。 - Guerlando OCs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接