Почему законно брать временный?

Исходя из C++, я довольно удивлен, что этот код действителен в Rust:

let x = &mut String::new();
x.push_str("Hello!");

В C++ вы не можете взять адрес временного, и временный не переживет выражение, в котором он появляется.

Как долго временный живет в Русте? И с тех пор x это только заем, кто владелец строки?

3 ответа

Решение

Почему законно брать временный?

Это законно по той же причине, что и в C++, потому что кто-то сказал, что так и должно быть.

Как долго временный живет в Русте? И с тех пор x это только заем, кто владелец строки?

Ссылка говорит:

время жизни временных значений обычно

  • самое сокровенное заявление; хвостовое выражение блока считается частью оператора, который включает в себя блок, или
  • выражение условия или условное выражение цикла, если временное создается в выражении условия if или if/else или в loop условное выражение выражения while.

Когда создается временное значение, которое присваивается let декларация, однако, временная создается с временем жизни включающего блока вместо этого, как с помощью оператора включения (let объявление) будет гарантированной ошибкой (так как указатель на временное будет храниться в переменной, но временное будет освобождено, прежде чем переменная может быть использована). Компилятор использует простые синтаксические правила, чтобы решить, какие значения присваиваются привязке let, и, следовательно, заслуживает более длительного временного времени жизни.

По сути, вы можете рассматривать свой код как:

let mut a_variable_you_cant_see = String::new();
let x = &mut a_variable_you_cant_see;
x.push_str("Hello!");

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

Из ржавчины

Временные жизни

При использовании выражения значения в большинстве контекстов выражения места создается временная безымянная область памяти, инициализированная для этого значения, и вместо этого выражение оценивается в этом месте

Это относится, потому что String::new() является выражением значения и быть чуть ниже &mut это находится в контексте выражения места. Теперь оператору ссылки нужно только пройти через эту временную ячейку памяти, поэтому он становится значением всей правой части (включая &mut).

Однако, когда создается выражение временного значения, которое назначается в объявлении let, вместо этого создается временное значение с временем жизни включающего блока.

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

Это также отвечает на этот вопрос о разнице между

let a = &String::from("abcdefg"); // ok!

а также

let a = String::from("abcdefg").as_str(); // compile error

Во втором варианте временное передается в as_str()так что его время жизни заканчивается в конце оператора.

MIR от Rust дает некоторое представление о природе временных; рассмотрим следующий упрощенный случай:

fn main() {
    let foo = &String::new();
}

и MIR, который он производит (стандартные комментарии заменены на мои):

fn main() -> () {
    let mut _0: ();
    scope 1 {
        let _1: &std::string::String; // the reference is declared
    }
    scope 2 {
    }
    let mut _2: std::string::String; // the owner is declared

    bb0: {                              
        StorageLive(_1); // the reference becomes applicable
        StorageLive(_2); // the owner becomes applicable
        _2 = const std::string::String::new() -> bb1; // the owner gets a value; go to basic block 1
    }

    bb1: {
        _1 = &_2; // the reference now points to the owner
        _0 = ();
        StorageDead(_1); // the reference is no longer applicable
        drop(_2) -> bb2; // the owner's value is dropped; go to basic block 2
    }

    bb2: {
        StorageDead(_2); // the owner is no longer applicable
        return;
    }
}

Вы можете видеть, что "невидимый" владелец получает значение до того, как ему назначена ссылка, и что ссылка отбрасывается перед владельцем, как и ожидалось.

То, в чем я не уверен, так это то, почему есть, казалось бы, бесполезный scope 2 и почему владелец не попадает внутрь какой-либо области; Я подозреваю, что MIR просто еще не готов на 100%.

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