首先,我读过这个问题:
所选答案只是告诉提问者使用标准库,而不是解释实现,如果我的目标是构建一些东西,那就很好。除了我试图了解堆栈的实现,同时遵循为 Java 编写的数据结构教科书(Robert Sedgwick 和 Kevin Wayne 的算法),他们通过调整数组大小来实现堆栈(第 136 页) .
我正在实现resize方法,结果发现数组的大小需要是一个常量表达式。
meta:Rust 中的数组称为切片吗?
use std::mem;
struct DynamicStack<T> {
length: uint,
internal: Box<[T]>,
}
impl<T> DynamicStack<T> {
fn new() -> DynamicStack<T> {
DynamicStack {
length: 0,
internal: box [],
}
}
fn resize(&mut self, new_size: uint) {
let mut temp: Box<[T, ..new_size]> = box unsafe { mem::uninitialized() };
// ^^ error: expected constant expr for array
// length: non-constant path in constant expr
// code for copying elements from self.internal
self.internal = temp;
}
}
为了简洁起见,编译器错误是这样的
.../src/lib.rs:51:23: 51:38 error: expected constant expr for array length: non-constant path in constant expr
.../src/lib.rs:51 let mut temp: Box<[T, ..new_size]> = box unsafe { mem::uninitialized() };
^~~~~~~~~~~~~~~
.../src/lib.rs:51:23: 51:38 error: expected constant expr for array length: non-constant path in constant expr
.../src/lib.rs:51 let mut temp: Box<[T, ..new_size]> = box unsafe { mem::uninitialized() };
^~~~~~~~~~~~~~~
Rust 中肯定有一种方法可以初始化一个数组,其大小在运行时确定(即使它不安全)?您能否也解释一下您的答案中发生了什么?
我认为可能可以根据
来实现堆栈struct DynamicStack<T> {
length: uint,
internal: Box<Optional<T>>
}
但是我不希望匹配可选值的开销来删除不安全的内存操作,但这仍然不能解决未知数组大小的问题。
我也尝试过这个(甚至无法编译)
fn resize(&mut self, new_size: uint) {
let mut temp: Box<[T]> = box [];
let current_size = self.internal.len();
for i in range(0, current_size) {
temp[i] = self.internal[i];
}
for i in range(current_size, new_size) {
temp[i] = unsafe { mem::uninitialized() };
}
self.internal = temp;
}
我得到了这个编译器错误
.../src/lib.rs:55:17: 55:21 error: cannot move out of dereference of `&mut`-pointer
.../src/lib.rs:55 temp[i] = self.internal[i];
^~~~
.../src/lib.rs:71:19: 71:30 error: cannot use `self.length` because it was mutably borrowed
.../src/lib.rs:71 self.resize(self.length * 2);
^~~~~~~~~~~
.../src/lib.rs:71:7: 71:11 note: borrow of `*self` occurs here
.../src/lib.rs:71 self.resize(self.length * 2);
^~~~
.../src/lib.rs:79:18: 79:22 error: cannot move out of dereference of `&mut`-pointer
.../src/lib.rs:79 let result = self.internal[self.length];
^~~~
.../src/lib.rs:79:9: 79:15 note: attempting to move value to here
.../src/lib.rs:79 let result = self.internal[self.length];
^~~~~~
.../src/lib.rs:79:9: 79:15 help: to prevent the move, use `ref result` or `ref mut result` to capture value by reference
.../src/lib.rs:79 let result = self.internal[self.length];
我也看过这个,但是我已经有一段时间没有做过任何 C/C++ 了
Rust 中肯定有一种方法可以在运行时确定其大小来初始化数组吗?
不,Rust 数组只能能够以编译时已知的大小创建。事实上,每个类型和大小的元组都构成了一个新类型! Rust 编译器使用该信息进行优化。
一旦您需要在运行时确定一组事情,您就必须添加运行时检查以确保 Rust 的“安全保证”始终有效。例如,您无法访问未初始化的内存(例如离开一组项目的开头或结尾)。 如果您真的想走这条路,我希望您将不得不亲自尝试一些直接的内存分配和不安全的代码。本质上,您将构建
Vec
本身的较小版本!为此,您可以查看
Vec的来源。 在较高层次上,您将需要分配足够大的内存块来容纳某种类型的 N 个对象。然后,您可以使用底层的指针算术来提供访问这些元素的方法。添加更多元素时,您可以分配更多空间并移动旧值。有很多微妙的事情可能会出现,也可能不会出现,但听起来你正处于一个有趣的旅程的开始! 编辑
当然,你可以选择假装
Vec
的大多数方法都不存在,而只使用与Java数组类似的方法。不过,您仍然需要使用
Option
来避免未初始化的值。