简体   繁体   English

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

[英]How to check if a Box is a null pointer?

I want to implement a stack using pointers or something.我想使用指针或其他东西来实现堆栈。 How can I check if a Box is a null pointer?如何检查Box是否为 null 指针? I seen some code with Option<Box<T>> and Box<Option<T>> but I don't understand this.我看到了一些带有Option<Box<T>>Box<Option<T>>的代码,但我不明白这一点。 This is as far as I went:这是我去的:

struct Node {
    value: i32,
    next: Box<Node>,
}

struct Stack {
    top: Box<Node>,
}

Box<T> can never be NULL, therefore there is nothing to check. Box<T>永远不会是 NULL,因此无需检查。

Box<T> values will always be fully aligned, non-null pointers Box<T>值将始终完全对齐,非空指针

std::box std::box

You most likely wish to use Option to denote the absence / presence of a value:您很可能希望使用Option来表示值的缺失/存在:

struct Node {
    value: i32,
    next: Option<Box<Node>>,
}

struct Stack {
    top: Option<Box<Node>>,
}

See also:也可以看看:

You don't want null .你不想要null null is an unsafe antipattern even in languages where you have to use it, and thankfully Rust rids us of the atrocity. null是一种不安全的反模式,即使在您必须使用它的语言中也是如此,幸运的是 Rust 使我们摆脱了暴行。 Box<T> always contains a T , never null . Box<T>始终包含T从不包含null Rust has no concept of null . Rust 没有null的概念。

As you've correctly pointed out, if you want a value to be optional, you use Option<T> .正如您正确指出的那样,如果您希望一个值是可选的,您可以使用Option<T> Whether you do Box<Option<T>> or Option<Box<T>> really doesn't matter that much, and someone who knows a bit more about the lower-level side of things can chime in on which is more efficient.不管你是做Box<Option<T>>还是Option<Box<T>>真的没那么重要,并且对事物的低级方面有更多了解的人可以插话哪个更有效。

struct Node {
    value: i32,
    next: Option<Box<Node>>,
}

struct Stack {
    top: Option<Box<Node>>,
}

The Option says "this may or may not exist" and the Box says "this value is on the heap. Now, the nice thing about Option that makes it infinitely better than null is that you have to check it. You can't forget or the compiler will complain. The typical way to do so is with match Option说“这可能存在也可能不存在”, Box说“这个值在堆上。现在, Optionnull更好的好处是你必须检查它。你不能忘记否则编译器会抱怨。这样做的典型方法是使用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>
    }
}

There are tons of helper methods on the Option type itself to deal with common patterns. Option类型本身有大量的辅助方法来处理常见的模式。 Below are just a few of the most common ones I use.以下只是我使用的一些最常见的。 Note that all of these can be implemented in terms of match and are just convenience functions.请注意,所有这些都可以根据match来实现,并且只是便利功能。

The equivalent of the following Java code相当于以下Java代码

if (value == null) {
  result = null;
} else {
  result = ...;
}

is

let result = value.map(|v| ...)

Or, if the inner computation can feasibly produce None as well,或者,如果内部计算也可以产生None

let result = value.and_then(|v| ...)

If you want to provide a default value, say zero, like如果你想提供一个默认值,比如零,比如

if (value == null) {
  result = 0;
} else {
  result = value;
}

Then you want那你想要

result = value.unwrap_or(0)

It's probably best to stop thinking in terms of how you would handle null and start learning Option<T> from scratch.最好停止思考如何处理null并从头开始学习Option<T> Once you get the hang of it, it'll feel ten times safer and more ergonomic than null checks.一旦掌握了窍门,它就会比null检查更安全、更符合人体工程学十倍。

A Box<T> is a pointer to some location on the heap that contains some data of type T . Box<T>是指向堆上某个位置的指针,其中包含一些T类型的数据。 Rust guarantees that Box<T> will never be a null pointer, ie the address should always be valid as long as you aren't doing anything weird and unsafe . Rust 保证Box<T>永远不会是 null 指针,即只要您没有做任何奇怪和unsafe的事情,地址就应该始终有效。

If you need to represent a value that might not be there (eg this node is the last node, so there is no next node), you can use the Option type like so如果您需要表示一个可能不存在的值(例如,此节点是最后一个节点,因此没有next节点),您可以像这样使用Option类型

struct Node {
    value: i32,
    next: Option<Box<Node>>,
}

struct Stack {
    top: Option<Box<Node>>,
}

Now, with Option<Box<Node>> , Node can either have a next Node or no next node.现在,使用Option<Box<Node>>Node可以有下一个Node ,也可以没有下一个节点。 We can check if the Option is not None like so我们可以检查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")
    }
}

Because a Box is just a pointer to some location on the heap, it can be better to use Option<Box<T>> instead of Box<Option<T>> .因为Box只是指向堆上某个位置的指针,所以最好使用Option<Box<T>>而不是Box<Option<T>> This is because the second one will allocate an Option<T> on the heap, while the first one will not.这是因为第二个将在堆上分配Option<T> ,而第一个不会。 Additionally, Option<Box<T>> and Box<T> are equally big (both are 8 bytes).此外, Option<Box<T>>Box<T>一样大(都是 8 个字节)。 This is because Rust knows that Box<T> can never be all zeros (ie can never be the null pointer), so it can use the all-0's state to represent the None case of Option<Box<T>> .这是因为 Rust 知道 Box Option<Box<T>> Box<T>永远不能全为零(即永远不能是 null 指针),所以它可以使用全 0 的None的情况来表示。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM