首先,我已经阅读了这个问题:
选择的答案只是告诉提问者使用标准库而不是解释实现,如果我的目标是构建一些东西,这很好。除了我试图了解堆栈的实现,同时遵循为Java (Algorithms by Robert Sedgwick& Kevin Wayne)编写的数据结构教科书,他们通过调整大小来实现堆栈数组(页136)。
我正在实现resize方法,结果发现数组的大小需要是一个常量表达式。
meta:是生锈的数组叫做切片吗?
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() };
^~~~~~~~~~~~~~~
当然,有一种生锈方法可以在运行时确定阵列的大小(即使它不安全)?你能否解释你的答案中发生了什么?
我认为根据
来实现堆栈可能是可能的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 ++之后已经有一段时间了
答案 0 :(得分:4)
当然在Rust中有一种方法可以初始化一个数组,其大小是在运行时确定的吗?
不,Rust数组只能能够使用编译时已知的大小创建。事实上,每个类型和大小的元组构成一个新类型! Rust编译器使用该信息进行优化。
一旦需要在运行时确定一组内容,就必须添加运行时检查以确保Rust的safety guarantees始终有效。例如,您无法访问未初始化的内存(例如,通过离开一组项目的开头或结尾)。
如果你真的想沿着这条路走下去,我希望你不得不用一些直接的内存分配和不安全的代码来解决问题。从本质上讲,您将构建一个较小版本的Vec
本身!为此,您可以查看source of Vec。
在较高级别,您需要分配大到足以容纳某些类型的N个对象的内存块。然后,您可以使用指针算法提供访问这些元素的方法。添加更多元素时,可以分配更多空间并移动旧值。有许多细微之处可能会或可能不会出现,但听起来你正处于一个有趣的旅程的开始!
修改强>
当然,您可以选择假装Vec
的大部分方法都不存在,只使用与Java数组类似的方法。您仍然需要使用Option
来避免未初始化的值。