Firstly, I’m going to publish some similar questions but which are not the same (despite having a similar title and subject), if you find the answer to my question in another post, please notify me in the comments, I really couldn’t find it.
| Question | Reason |
|---|---|
| Use `Option` to maybe allocate? | Although I understand that Option does not occupy the total space of Algo until there is Some, I am referring to an array of Option elements that will most likely be allocated on the Heap instead of a simple Option |
| https://stackoverflow.com/questions/47876592/what-is-the-most-memory-efficient-array-of-nullable-vectors-when-most-of-the-sec | He is making reference to a type of dynamic allocation, which is vec, so, despite the author asking about the efficiency of Option<> (which according to the answer is the same), it is not the same as my question that makes reference to an array of fixed type and size and not a dynamic data type |
| https://stackoverflow.com/questions/28656387/initialize-a-large-fixed-size-array-with-non-copy-types | He is asking about how to initialize with None, but unfortunately it didn’t help to know whether the None inside the array (which is a data type of fixed size and type) will occupy additional size in memory or not. |
The question
Consider the following code below
fn main() {
let my_array: [Option<MyStruct>; 5] = [
Some(MyStruct{ field1: 1, field2: 2, field3: 3 }),
Some(MyStruct{ field1: 1, field2: 2, field3: 3 }),
None,
Some(MyStruct{ field1: 1, field2: 2, field3: 3 }),
None,
];
}
struct MyStruct {
field1: i32,
field2: i32,
field3: i32,
}
Taking into account using an array of type Option<MyStruct> with size set to 5, will it occupy the 12 bytes + the option enum flag even when the element at index position 2 of the array is None?
Or it will allocate the 12 bytes when the element at index 2 position of the array is Some(MyStruct)
If the Rust compiler is not efficient enough for this, what is the equivalent of the following in C++:
#include <iostream>
struct Example {
int a;
int b;
};
int main(){
Example* examples[5];
/*Initialize examples at position 2*/
examples[2] = new Example;
return 0;
}
In other words, notice that C++ stored a pointer, that is, it did not need to store 12 bytes (three integers) of the structure Example
>Solution :
A Box<T> is a non-nullable pointer in Rust. An Option<T> is either a None or a Some(T), but Option<T> (as noted in the related answers you link) always allocates enough space for T. So in your example, there’s no pointer indirection, and every element of my_array takes up size_of<MyStruct>() space in bytes.
But we can put the two puzzle pieces together. An Option<Box<T>> is a potentially-nullable pointer to a T. The size of a Box<T> is just the size of a pointer, so whether or not the value is there, the Option<Box<T>> only needs one pointer’s worth of space in automatic memory. The dynamic storage of the value pointed to is only allocated if needed, just like in C++. And Rust even has a specific optimization to ensure that Option<Box<T>> works just like a T* under the hood. That is, in this particular case, we don’t even need to store the "is Option empty" discriminator, since we can just use the otherwise-unused nullptr value for the underlying pointer to represent that.
So you want an array of Option<Box<T>> whose values are all initially None. Then you can set some of them to Some(Box::new(whatever)) and get the allocation when you need it.