问题描述
我想用指针什么的来实现一个堆栈。如何检查 Box
是否为空指针?我看到了一些带有 Option<Box<T>>
和 Box<Option<T>>
的代码,但我不明白这一点。这就是我所走的:
struct Node {
value: i32,next: Box<Node>,}
struct Stack {
top: Box<Node>,}
解决方法
Box<T>
永远不能为 NULL,因此无需检查。
Box<T>
值将始终完全对齐,非空指针
——std::box
您很可能希望使用 Option
来表示值的缺失/存在:
struct Node {
value: i32,next: Option<Box<Node>>,}
struct Stack {
top: Option<Box<Node>>,}
另见:
- Should we use Option or ptr::null to represent a null pointer in Rust?
- How to set a field in a struct with an empty value?
- What is the null pointer optimization in Rust?
你不想要null
。 null
是一种不安全的反模式,即使在您必须使用它的语言中,谢天谢地,Rust 使我们摆脱了这种暴行。 Box<T>
always 包含一个 T
,never null
。 Rust 没有 null
的概念。
正如您正确指出的那样,如果您希望某个值是可选的,请使用 Option<T>
。你是做 Box<Option<T>>
还是 Option<Box<T>>
真的没有那么重要,对底层事物有更多了解的人可以说哪个更有效。
struct Node {
value: i32,}
Option
表示“这可能存在也可能不存在”,而 Box
表示“这个值在堆上。现在,Option
的好处使它无限好与 null
相比,您必须检查它。您不能忘记,否则编译器会抱怨。这样做的典型方法是使用 {{1 }}
match
match my_stack.top {
None => {
// Top of stack is not present
}
Some(x) => {
// Top of stack exists,and its value is x of type Box<T>
}
}
类型本身有 tons of helper methods 来处理常见模式。下面只是几个最常见的我用的。请注意,所有都可以根据 Option
实现并且只是方便的函数。
相当于下面的Java代码
match
是
if (value == null) {
result = null;
} else {
result = ...;
}
或者,如果内部计算也可以可行地产生 let result = value.map(|v| ...)
,
None
如果您想提供默认值,请说零,例如
let result = value.and_then(|v| ...)
然后你想要
if (value == null) {
result = 0;
} else {
result = value;
}
最好停止思考如何处理 result = value.unwrap_or(0)
并从头开始学习 null
。一旦掌握了它,您就会觉得它比 Option<T>
检查更安全、更符合人体工程学。
Box<T>
是指向堆上某个位置的指针,该位置包含一些 T
类型的数据。 Rust 保证 Box<T>
永远不会是空指针,即只要你没有做任何奇怪的事情和 unsafe
,地址应该总是有效的。
如果你需要表示一个可能不存在的值(例如这个节点是最后一个节点,所以没有next
节点),你可以像这样使用Option
类型>
struct Node {
value: i32,}
现在,使用 Option<Box<Node>>
,Node
可以有下一个 Node
或没有下一个节点。我们可以检查 Option
是否不是 None
那样
fn print_next_node_value(node: &Node) {
match &node.next {
Some(next) => println!("the next value is {}",next.value),None => println!("there is no next node")
}
}
因为 Box
只是指向堆上某个位置的指针,所以最好使用 Option<Box<T>>
而不是 Box<Option<T>>
。这是因为第二个会在堆上分配一个 Option<T>
,而第一个不会。此外,Option<Box<T>>
和 Box<T>
一样大(都是 8 个字节)。这是因为 Rust 知道 Box<T>
永远不可能全为零(即永远不可能是空指针),所以它可以使用全 0 的状态来表示 None
的 Option<Box<T>>
情况.