Что является более традиционным - передавать по значению или по ссылке, когда методу требуется владение значением?

Когда я передаю объект по ссылке на метод структуры new(), и структура будет владеть объектом, является ли более традиционным следующее:

  • передать объект по ссылке и сделать to_owned() в new()
  • клонировать объект перед вызовом new() и передавать по значению, перемещая его

Я могу думать о плюсах и минусах каждого с точки зрения ясности и разделения проблем.

#[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());
}

person Andrew Moffat    schedule 19.05.2020    source источник
comment
если вам нужно собственное судно, спросите собственника, если нет, не делайте этого.   -  person Stargateur    schedule 19.05.2020
comment
Я думаю, @Shepmaster отредактировал мой исходный вопрос слишком агрессивно. Моя структура требует владения копией, а не оригинала.   -  person Andrew Moffat    schedule 19.05.2020
comment
нет большой разницы, если вам нужен принадлежащий объект, который вы должны запросить, вызывающий может решить, клонировать или передать владение   -  person kmdreko    schedule 19.05.2020
comment
В частности, @AndrewMoffat, ваша структура не может знать, что это копия, потому что это только то, что может решить создатель структуры.   -  person Shepmaster    schedule 19.05.2020


Ответы (1)


Передайте по значению.

Таким образом, программа может избежать ненужного двойного выделения значения, если оно больше не нужно вызывающему.


Во многих случаях я рекомендую принимать все, что можно в принадлежащий тип. Это легко продемонстрировать с помощью 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"));
}

Смотрите также:

person Shepmaster    schedule 19.05.2020