Search code examples
rustreferenceborrow-checkerownershipborrowing

Is there a difference between using a reference, and using an owned value in Rust?


I'm reading the Rust book. It explains that when you create a function, you need to decide if your function will take ownership of its arguments, or take them as a mutable or immutable references.

What I'm not entirely clear about is if there's a syntactic difference between using an owned value within that function, or using a reference.

If you have a reference to a struct with methods, is the syntax for using those methods exactly the same as it would be if you were dealing with an owned variable? Are there any other difference between how one would use an owned variable, and how one would use a reference to that variable?

When do you need to dereference a reference variable? I've only seen dereferencing when you're trying to increment the value stored by the variable pointed to by a mutable reference to an int, or something like that. It seems like you only need to dereference it if you intend to replace the value of the variable entirely with something new. For example, if you want to run a method on a reference to a struct, you don't need to dereference, but if you want to replace the value with a completely difference instance of that struct, you need to dereference. Is that right?


Solution

  • If you have a reference to a struct with methods, is the syntax for using those methods exactly the same as it would be if you were dealing with an owned variable? Are there any other difference between how one would use an owned variable, and how one would use a reference to that variable?

    Yes, except if you have an immutable reference you're restricted to only calling methods which take immutable references, and if you have a mutable reference you can call methods which take mutable or immutable references, and if you have ownership you can call any method, including those which take ownership. Example:

    struct Struct;
    
    impl Struct {
        fn takes_self_ref(&self) {}
        fn takes_self_mut_ref(&mut self) {}
        fn takes_self(self) {}
    }
    
    fn func_owned(mut s: Struct) {
        s.takes_self_ref(); // compiles
        s.takes_self_mut_ref(); // compiles
        s.takes_self(); // compiles
    }
    
    fn func_mut_ref(s: &mut Struct) {
        s.takes_self_ref(); // compiles
        s.takes_self_mut_ref(); // compiles
        s.takes_self(); // error
    }
    
    fn func_ref(s: &Struct) {
        s.takes_self_ref(); // compiles
        s.takes_self_mut_ref(); // error
        s.takes_self(); // error
    }
    

    When do you need to dereference a reference variable?

    The deference operator *, however references are automatically dereferenced by the compiler on method calls which is why you rarely see the deference operator used in Rust code in practice, since it's rarely explicitly needed.