1
Jirajine 2020-09-20 11:07:44 +08:00 via Android
为什么要用原始数组呢,用 vector 啊。
let v1:Vec<i32> = (1..10).collect(); |
2
Jirajine 2020-09-20 11:15:17 +08:00 via Android
至于初始化,直接声明的变量是分配在栈上的,编译时就已确定,所以不用额外分配空间。
所有变量访问时必须初始化是 rust 静态检查的要求,未初始化当然可以赋值,只要访问前赋值了就行。 你这个数组不能的原因是 arr[i]本身就是一次访问,调用 index 方法,而 rust 不允许访问未初始化的变量。 |
4
noe132 2020-09-20 13:24:14 +08:00
Java 在你 new 的时候自动帮你把每个值赋值初始值了。
https://stackoverflow.com/a/3426854/6403587 |
5
CSM 2020-09-20 13:34:08 +08:00 via Android
你需要区分开引用类型与值类型。
> 那么 cargo check 会在 arr[i] = i as i32;处提示数组未初始化 这里的意思不是说数组的内容没有初始化(事实上,写入没有初始化的内存是允许的,并且是个重要的优化手段),而是指 arr 这个变量名字没有绑定到内存上, |
6
CSM 2020-09-20 13:43:54 +08:00
> let mut arr: [i32; 10]; // 仅声明一个数组,未初始化
这里只是定义了个名字。 在 Java 中 `int[] arr` 的意思是定义一个引用,但是因为还没有被赋值,是 null 。 在 C/C++ 中,`int arr[]` 后就已经在栈为数组预留了空间,此时已经可以写入了(虽然可以读取,但会是一些没用的数据,在 C/C++ 中给出警告,而 Rust 会禁止读取),但是在 Java 中还只是个指针,需要在堆为数组分配了内存(并赋值给这个指针)后才能写入。 |
8
qefrgty 2020-09-20 16:58:00 +08:00 via Android
没有。数组必须在声明时直接初始化。
单就你这段代码,能优化的地方就是第二行代码中的 :[i33;0] 可以删掉。 写 rust 你就相信编译器并满足它就完事儿了。 不过不必纠结数组,直接 vec 一把梭(大雾) |
10
0gre2019 OP 我暂时解决了,大体是用 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, } } } |
11
ldm0 2020-09-20 22:00:33 +08:00
```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> |
12
RedL0tus 2020-09-21 04:55:06 +08:00 via iPhone
说句题外话(
原始数组各方面比较接近 C 的数组,用的时候基本上都是使用它的 immutable reference ;应用场景除了 slice 或者像 nom 那样搞 zero-copy 极致性能之外就没多少了( 就我自己理解的话,一般用 Vec 是最合适的(反正 Vec 可以直接 AsRef 成 &[T]),还有一个 vec! 宏可以用,很方便的( |
16
CSM 2020-09-23 18:38:40 +08:00 via Android
@ldm0 不是,你这还没有初始化就转换了,虽说随后就写入了初始化的值,但创建未初始化的内存立马就是 UB 啊,不应该是初始化完成后再转换吗?
|