What is the difference between how references and Box are represented in memory?

前端 未结 2 1178
独厮守ぢ
独厮守ぢ 2021-02-07 17:08

I am trying to understand how references and Box work. Let\'s consider a code example:

fn main() {
    let x = 5;
    let y = &x;

             


        
2条回答
  •  一生所求
    2021-02-07 18:06

    While the general rule is exactly the same as in that answer What are the differences between Rust's `String` and `str`?, I'm answering here as well.

    A Rust reference is (almost) exactly what you have described: a pointer to the value somewhere in the memory. (It's not always. For example, slices also contain a length and pointers to traits also contain a v-table. These are called fat pointers). At the start, the Box is a value, like any other value in Rust, so the difference is obvious - one is a reference to a place in memory and the second is a value somewhere in memory. The confusion is that Box internally contains a reference to memory, but that reference is allocated on the heap instead of stack. The difference between these two is that the stack is function local and is quite small (on my macOS it is max 8192 KiB).

    For example, you cannot do something like this for a few reasons:

    fn foo() -> &u32 {
        let a = 5;
    
        &a
    }
    

    The most important reason is that a will not be there after foo() returns. That memory will be wiped out (not always though) and it is possible that it will be changed to another value soon. This is undefined behavior in C and C++ and an error in Rust which does not allow for any undefined behavior (in code that does not use unsafe).

    On the other hand, if you do:

    fn foo() -> Box {
        let a = Box::new(5);
    
        a
    }
    

    A few things relevant to us will happen:

    • memory will be allocated on the stack. This memory is totally independent from the current function scope, which means that it need to be freed when it will not be needed
    • we will move the value, so there are no lifetimes involved
    • ownership of a will be moved to the caller

    For convenience, Box will behave like a reference in many cases, as these two can be often used interchangeably. For example, see this C program where we provide similar functionality to the second example:

    int* foo(void) {
      int* a = malloc(sizeof(int));
      *a = 5;
    
      return a;
    }
    

    As you can see, the pointer is used to store the address of the memory and this is passed further.

提交回复
热议问题