如何检查 Box 是否为空指针?

问题描述

我想用指针什么的来实现一个堆栈。如何检查 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>>,}

另见:

,

你不想要nullnull 是一种不安全的反模式,即使在您必须使用它的语言中,谢天谢地,Rust 使我们摆脱了这种暴行。 Box<T> always 包含一个 Tnever 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 的状态来表示 NoneOption<Box<T>> 情况.