Search code examples
rustreferencepass-by-referencepass-by-value

Is it more conventional to pass-by-value or pass-by-reference when the method needs ownership of the value?


When I'm passing a object by reference to a struct's new() method, and the struct will own the object, is it more conventional to:

  • pass the object by reference, and do to_owned() in the new()
  • clone the object before calling new(), and pass by value, moving it

I can think of pros and cons of each in terms of clarity and separation-of-concerns.

#[derive(Clone)]
struct MyState;

struct MyStruct {
    state: MyState,
}

impl MyStruct {
    pub fn new_by_ref(state: &MyState) -> Self {
        MyStruct {
            state: state.to_owned(),
        }
    }

    pub fn new_by_val(state: MyState) -> Self {
        MyStruct { state }
    }
}

fn main() {
    let state1 = MyState;
    let struct1 = MyStruct::new_by_ref(&state1);

    let state2 = MyState;
    let struct2 = MyStruct::new_by_val(state2.clone());
}

Solution

  • Pass by value.

    This way, the program can avoid unnecessarily doubly-allocating the value if the caller no longer needs it.


    In many cases, I recommend accepting anything that can be made into the owned type. This is easily demonstrated with String:

    struct MyStruct {
        state: String,
    }
    
    impl MyStruct {
        fn new(state: impl Into<String>) -> Self {
            let state = state.into();
            MyStruct { state }
        }
    }
    
    fn main() {
        let struct1 = MyStruct::new("foo");
        let struct2 = MyStruct::new(String::from("bar"));
    }
    

    See also: