Как работает семантика перемещения при назначении поля структуры переменной?

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

struct Foo {
    bar: String,
    bazs: Vec<String>,
}


fn main() {
    let a: Foo = Foo {
        bar: "bar".to_string(),
        bazs: vec!["baz_1".to_string(), "bax_2".to_string()],
    };
    
    let b: String = a.bar;
    
    println!{"Who owns the String value, variable a or b? {b}"};
    
    // assigning a String (from a field of String type) to b IS NOT considered a move
    // assigning a String (from an element of field of Vec<String> type to IS considered a move
    // let c: String = a.bazs[0];
}

Ржавая площадка

Пример основан на прочтении книги о языке программирования Rust по отношению к этим разделам, в которых обсуждается перемещение строк, но пока не дает мне достаточных оснований для понимания этого построенного примера:

Надеюсь получить несколько подсказок, как правильно разобраться в этом вопросе.

@kmdreko Извиняюсь за мое невежество и не поясняю это в исходном примере, но я ожидал увидеть проблему, которую заполнил BallpointBen, и заключающуюся в том, что я не смогу использовать структуру целиком после перемещения ее поля. . Не зная частичных ходов, я не смог бы представить приведенные ниже примеры.

Ming Ma 25.03.2024 06:47
Почему Python в конце концов умрет
Почему Python в конце концов умрет
Последние 20 лет были действительно хорошими для Python. Он прошел путь от "просто языка сценариев" до основного языка, используемого для написания...
1
1
56
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

У ржавчины есть частичные ходы. Вы можете переместить a.bar и a.bazs из a по отдельности. Чего вы не можете сделать, так это использовать a целиком после перемещения любого из его (не Copy) полей. Но отдельные неподвижные поля по-прежнему остаются честной добычей. Так что это нормально:

let a: Foo = Foo {
    bar: "bar".to_string(),
    bazs: vec!["baz_1".to_string(), "bax_2".to_string()],
};

let b = a.bar;
let bazs = a.bazs;

Хотя этого нет:

let a: Foo = Foo {
    bar: "bar".to_string(),
    bazs: vec!["baz_1".to_string(), "bax_2".to_string()],
};

let b = a.bar;
let new_a = a;

Вот увидишь

error[E0382]: use of partially moved value: `a`
partial move occurs because `a.bar` has type `std::string::String`,
which does not implement the `Copy` trait

Другие вопросы по теме