12

The standard library's linked-list Node uses the Option type:

struct Node<T> {
    next: Option<NonNull<Node<T>>>,
    prev: Option<NonNull<Node<T>>>,
    element: T,
}

and creates a node with this code:

Node {
    next: None,
    prev: None,
    element,
}

The implementation of LeafNode of BTree, the standard library uses a raw pointer for the parent node:

struct LeafNode<K, V> {
    parent: *const InternalNode<K, V>,
    parent_idx: MaybeUninit<u16>,
    len: u16,
    keys: MaybeUninit<[K; CAPACITY]>,
    vals: MaybeUninit<[V; CAPACITY]>,
}

and creates new leaf nodes by setting parent to ptr::null:

LeafNode {
    keys: MaybeUninit::uninitialized(),
    vals: MaybeUninit::uninitialized(),
    parent: ptr::null(),
    parent_idx: MaybeUninit::uninitialized(),
    len: 0
}

We can use nullptr to implement the above code in C++, so what's the difference between Option and std::ptr::null() to represent a null pointer? What's the recommended way to represent a null pointer?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
McGrady
  • 10,869
  • 13
  • 47
  • 69
  • Are you asking for the difference between using `Option>` and `*mut T`? – E_net4 Jan 15 '19 at 09:27
  • @E_net4wisheshappyholidays I mean, what's the difference between Option and std::ptr::null() to implement nullptr, which way is recommended to implement nullptr? – McGrady Jan 15 '19 at 09:33

1 Answers1

12

In general, I'd recommend using NonNull<T> over *const T or *mut T, using Option as appropriate to identify when the pointer may be null.

The reason is two-fold:

  1. Whether null is a valid value, or not, is documented and enforced when using NonNull.
  2. *const T and *mut T are essentially interchangeable, and indeed can be cast to one another, so that const or mut may provide a false sense of safety.

The implementation of BTree may simply not have been ported over to NonNull, which is relatively recent -- it was stabilized only in 1.25.

Matthieu M.
  • 287,565
  • 48
  • 449
  • 722