如何检查 Box 是否为空指针?
How to check if a Box is a null pointer?
我想用指针什么的实现一个栈。如何检查 Box
是否为空指针?我看到一些带有 Option<Box<T>>
和 Box<Option<T>>
的代码,但我不明白这一点。这是我去的最远的地方:
struct Node {
value: i32,
next: Box<Node>,
}
struct Stack {
top: Box<Node>,
}
Box<T>
永远不能为 NULL,因此无需检查。
Box<T>
values will always be fully aligned, non-null pointers
— std::box
您很可能希望使用 Option
来表示值的不存在/存在:
struct Node {
value: i32,
next: Option<Box<Node>>,
}
struct Stack {
top: Option<Box<Node>>,
}
另请参阅:
你不想要 null
。 null
是一种不安全的反模式,即使在您 必须 使用它的语言中也是如此,幸运的是 Rust 让我们摆脱了这种暴行。 Box<T>
always 包含 T
、never null
。 Rust 没有 null
.
的概念
正如您正确指出的那样,如果您希望某个值是可选的,请使用 Option<T>
。你做 Box<Option<T>>
还是 Option<Box<T>>
真的没那么重要,对事情的底层了解多一点的人可以插话说哪个更有效率。
struct Node {
value: i32,
next: Option<Box<Node>>,
}
struct Stack {
top: Option<Box<Node>>,
}
Option
说“这可能存在也可能不存在”,Box
说“这个值在堆上。现在,Option
的好处就是它比 null
好得多的是你 有 来检查它。你 不能 忘记否则编译器会抱怨。典型的方式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>
}
}
Option
类型本身有 tons of helper methods 来处理常见的模式。下面只是我使用的一些最常用的。请注意,所有 都可以根据 match
实现,并且只是方便的功能。
相当于下面的Java代码
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>
。一旦掌握了它,它会感觉比 null
检查安全十倍,更符合人体工学。
A Box<T>
是指向堆上某个位置的指针,其中包含一些 T
类型的数据。 Rust 保证 Box<T>
永远不会是空指针,即只要你没有做任何奇怪的事情并且 unsafe
.
地址应该总是有效的
如果你需要表示一个可能不存在的值(例如这个节点是最后一个节点,所以没有 next
节点),你可以像这样使用 Option
类型
struct Node {
value: i32,
next: Option<Box<Node>>,
}
struct Stack {
top: Option<Box<Node>>,
}
现在,对于 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 的状态来表示 Option<Box<T>>
的 None
情况.
我想用指针什么的实现一个栈。如何检查 Box
是否为空指针?我看到一些带有 Option<Box<T>>
和 Box<Option<T>>
的代码,但我不明白这一点。这是我去的最远的地方:
struct Node {
value: i32,
next: Box<Node>,
}
struct Stack {
top: Box<Node>,
}
Box<T>
永远不能为 NULL,因此无需检查。
Box<T>
values will always be fully aligned, non-null pointers—
std::box
您很可能希望使用 Option
来表示值的不存在/存在:
struct Node {
value: i32,
next: Option<Box<Node>>,
}
struct Stack {
top: Option<Box<Node>>,
}
另请参阅:
你不想要 null
。 null
是一种不安全的反模式,即使在您 必须 使用它的语言中也是如此,幸运的是 Rust 让我们摆脱了这种暴行。 Box<T>
always 包含 T
、never null
。 Rust 没有 null
.
正如您正确指出的那样,如果您希望某个值是可选的,请使用 Option<T>
。你做 Box<Option<T>>
还是 Option<Box<T>>
真的没那么重要,对事情的底层了解多一点的人可以插话说哪个更有效率。
struct Node {
value: i32,
next: Option<Box<Node>>,
}
struct Stack {
top: Option<Box<Node>>,
}
Option
说“这可能存在也可能不存在”,Box
说“这个值在堆上。现在,Option
的好处就是它比 null
好得多的是你 有 来检查它。你 不能 忘记否则编译器会抱怨。典型的方式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>
}
}
Option
类型本身有 tons of helper methods 来处理常见的模式。下面只是我使用的一些最常用的。请注意,所有 都可以根据 match
实现,并且只是方便的功能。
相当于下面的Java代码
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>
。一旦掌握了它,它会感觉比 null
检查安全十倍,更符合人体工学。
A Box<T>
是指向堆上某个位置的指针,其中包含一些 T
类型的数据。 Rust 保证 Box<T>
永远不会是空指针,即只要你没有做任何奇怪的事情并且 unsafe
.
如果你需要表示一个可能不存在的值(例如这个节点是最后一个节点,所以没有 next
节点),你可以像这样使用 Option
类型
struct Node {
value: i32,
next: Option<Box<Node>>,
}
struct Stack {
top: Option<Box<Node>>,
}
现在,对于 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 的状态来表示 Option<Box<T>>
的 None
情况.