跳至主要內容
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?

4563博客

全新的繁體中文 WordPress 網站
  • 首頁
  • 刚开始学 Rust,这是一段创建一个原始数组的代码,有更“官方”的实现吗?
未分類
14 9 月 2020

刚开始学 Rust,这是一段创建一个原始数组的代码,有更“官方”的实现吗?

刚开始学 Rust,这是一段创建一个原始数组的代码,有更“官方”的实现吗?

資深大佬 : 0gre2019 2

原 Java 代码:
int[] arr = new int[10];
for(int i = 0;i < arr.length;i ++)
arr[i] = i;

我捣鼓的 Rust 代码:
fn main() {
let mut arr: [i32; 10] = [0; 10];

for i in 0..arr.len() {
arr[i] = i as i32;
}
}

有个疑问:
1. Rust 的原始数组似乎是没有“new”这种特性,即提前开辟一个空间。必须在声明时同时初始化?假如我如下面这样写:

let mut arr: [i32; 10]; // 仅声明一个数组,未初始化

那么 cargo check 会在 arr[i] = i as i32;处提示数组未初始化,有比我这个更好的写法吗,即数组初始化方法?

(另外吐槽下 Rust 真的很严格,循环里的赋值代码必须写 as i32,好像不准隐式转换 usize 到 i32 。。)

大佬有話說 (14)

  • 資深大佬 : Jirajine

    为什么要用原始数组呢,用 vector 啊。
    let v1:Vec<i32> = (1..10).collect();

  • 資深大佬 : Jirajine

    至于初始化,直接声明的变量是分配在栈上的,编译时就已确定,所以不用额外分配空间。
    所有变量访问时必须初始化是 rust 静态检查的要求,未初始化当然可以赋值,只要访问前赋值了就行。
    你这个数组不能的原因是 arr[i]本身就是一次访问,调用 index 方法,而 rust 不允许访问未初始化的变量。

  • 主 資深大佬 : 0gre2019

    @Jirajine 因为刚学,想把一个 Java 实现的数据结构用 Rust 重写一下来练习。。

  • 資深大佬 : noe132

    Java 在你 new 的时候自动帮你把每个值赋值初始值了。
    https://stackoverflow.com/a/3426854/6403587

  • 資深大佬 : CSM

    你需要区分开引用类型与值类型。

    > 那么 cargo check 会在 arr[i] = i as i32;处提示数组未初始化

    这里的意思不是说数组的内容没有初始化(事实上,写入没有初始化的内存是允许的,并且是个重要的优化手段),而是指 arr 这个变量名字没有绑定到内存上,

  • 資深大佬 : CSM

    > let mut arr: [i32; 10]; // 仅声明一个数组,未初始化

    这里只是定义了个名字。

    在 Java 中 `int[] arr` 的意思是定义一个引用,但是因为还没有被赋值,是 null 。
    在 C/C++ 中,`int arr[]` 后就已经在栈为数组预留了空间,此时已经可以写入了(虽然可以读取,但会是一些没用的数据,在 C/C++ 中给出警告,而 Rust 会禁止读取),但是在 Java 中还只是个指针,需要在堆为数组分配了内存(并赋值给这个指针)后才能写入。

  • 主 資深大佬 : 0gre2019

    @CSM 好像更理解了一些,谢谢

  • 資深大佬 : qefrgty

    没有。数组必须在声明时直接初始化。

    单就你这段代码,能优化的地方就是第二行代码中的 :[i33;0] 可以删掉。

    写 rust 你就相信编译器并满足它就完事儿了。

    不过不必纠结数组,直接 vec 一把梭(大雾)

  • 主 資深大佬 : 0gre2019

    @qefrgty : )谢谢

  • 主 資深大佬 : 0gre2019

    我暂时解决了,大体是用 Box 包装了一下:
    #[derive(Debug)]
    pub struct Array {
    data: Box::<[i32]>,
    size: usize,
    }

    impl Array {
    pub fn new() -> Array {
    Array {
    data: Box::new([0; 100]),
    size: 0,
    }
    }
    }

  • 資深大佬 : ldm0

    “`rust
    use std::mem::{self, MaybeUninit};

    fn main() {
    let mut arr = unsafe {
    let data: [MaybeUninit<i32>; 10] = MaybeUninit::uninit().assume_init();
    mem::transmute::<_, [i32; 10]>(data)
    };

    for i in 0..arr.len() {
    arr[i] = i as i32;
    }

    dbg!(arr);
    }
    “`
    参见 <https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html>

  • 資深大佬 : RedL0tus

    说句题外话(

    原始数组各方面比较接近 C 的数组,用的时候基本上都是使用它的 immutable reference ;应用场景除了 slice 或者像 nom 那样搞 zero-copy 极致性能之外就没多少了(

    就我自己理解的话,一般用 Vec 是最合适的(反正 Vec 可以直接 AsRef 成 &[T]),还有一个 vec! 宏可以用,很方便的(

  • 主 資深大佬 : 0gre2019

    @ldm0 老哥你这是终极解决方案,我看了 Vec 的源码,基础数据类型就是 MaybeUninit<T>,谢了!

  • 資深大佬 : CSM

    @ldm0 是不是 transmute 的太早了……

文章導覽

上一篇文章
下一篇文章

AD

其他操作

  • 登入
  • 訂閱網站內容的資訊提供
  • 訂閱留言的資訊提供
  • WordPress.org 台灣繁體中文

51la

4563博客

全新的繁體中文 WordPress 網站
返回頂端
本站採用 WordPress 建置 | 佈景主題採用 GretaThemes 所設計的 Memory
4563博客
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?
在這裡新增小工具