Noting during learning a safe language with checkers
Box<T> for an owning(unique) pointer to
Box::new() to allocate space on the heap and initialise that space with the supplied value.
Owning pointera are derefenced with
In Rust, you can't have a mutable pointer to immutable data.
Owning pointers can be returned from a function and continue to live on. If they are returned, their memory is not freed, i.e., there are no dangling pointers in Rust. However, once out of scope , the memory will be reclaimed.
When one pointer points at a value, any previous pointer pointing to that value can no longer be accessed. Similarly, if an owning pointer is passed to another function or stored in a field, it can no longer be accessed.
unique_ptris checked dynamically, while Rust's owning pointer is checked statically.
Method calls can automatically dereference.
Box::new() with an existing value copy that value rather than taking reference.
To create a reference to an existing value, we have to use
&, the borrowed reference operator. And to dereference it, use
* as well. The
& operator does not allocate memory, and if it goes out of scope, no memory will be reclaimed correspondingly.
Mutable reference are taken with
&mut, and it is unique.
And you can't have a mutable reference to an immutable variable.
The reference may be mutable independently of the mutableness of the variable holding the reference.
If a mutable value is borrowed, it becomes immutable for the duration of the borrow. Once the borrowed pointer goes out of scope, the value can be mutated again.
The lifetime of the reference must be shorter than the lifetime of the referenced value.
&T is a shorthant for
&'a T where
a is the current scope, that is the scope in which the type is declared.
Ref count and raw pointers
Ref-counted pointer is from
To pass a ref-counted pointer, a
clone method is needed.
To have mutable & ref-counted object, a
RefCell wrapped in an Rc is needed.
*T -- unsafe pointers
Unsafe pointers are donated as
*T and created with
&. Specifing the type to distinct unsafe pointer from borrowed reference. They can't be dereferenced outside of an
unsafe block, only to be passed around in regular Rust code.
Unsafe pointers are immutable by default, and can be made mutable like
In Rust, the data abstraction and behaviour abstraction are more seperated. The behaviour is defined by functions as
impl of "traits". But "traits" can't contain data. For data, there are
Struct cannot be recursive. But you can use pointers to create data-level recursion.
Tuple struct is kinda mixture of
tuple. For example,
struct IntPoint (i32, i32)
enum in Rust, each variant can carry data, like tagged union. Many simple OO poly can be handle with Rust
RefCell structs, parts of immutable objects can be mutated.
set methods for changing the stored value, and a
new method to initialize the cell with a value.
RefCell are used for types with
set methods, but to get its value,
borrow must be used, like
To create a reference to something in a pattern, you have to use the
i32 has copy semantics while
Box<i32> has move semantics.
Rust determines if an object has move or copy semantics by looking for destructors. An object has a destructor if it implements
When we get a reference to some data and need the value itself, you need to use/implement
clone or make a manual copy.
In Rust, mutability is inherited.
Array, Slice and Vector
Since the compiler must know the size of all objects in Rust, and it can't know the size of a slice, then we can never have a value with slice type. So, we must always have pointers to slices.
Array is fixed length, slice is dynamically sized, while the vector is heap allocated as an owning reference.
Array is a value, slice is like borrowed reference, and vector is like a owned pointer.
Graphs and Arena Allocation
Since graphs can be cyclic, and ownership in Rust cannot be cyclic, so we cannot use
Box<Node> as our pointer type. And mutabability is also a problem during the process of computation.
One solution is to use mutable raw pointers e.g.
*mut Node, this is rather flexible but also dangerous.
Another solution: For lifetime management, use ref-counting, which solves the shared ownership problem, or you can use arena allocation (all nodes have the same lifetime, managed by an arena, using borrowed references
&). For managing mutability, you can either use
So, this is basically a 2v2 combination:
- Lifetime: ref-counting or arena allocation
Aerna allocation is a memory management technique where a set of objects have the same lifetim and can be deallocated at the same time. An arena is an object responsible for allocating and deallocating the memory. Since large chunks of memory are allocated and deallocated at once, so ti is efficient and cache-friendly.