EN VI

C++ - Does array of Option takes up memory in Rust when Option is None?

2024-03-16 11:30:04
C++ - Does array of Option takes up memory in Rust when Option is None?

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.

Answer

Login


Forgot Your Password?

Create Account


Lost your password? Please enter your email address. You will receive a link to create a new password.

Reset Password

Back to login