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

Когда неназванные значения выходят из области видимости, когда значение отбрасывается?

Я ищу ответ, основанный на официальных документах, а не на экспериментах.

Пример 1:

f(foo().bar());

Пример 2:

match foo().bar() {
    // ...
}

Если bar является fn bar(self) -> ... он переходит в собственность переданного значения и отбрасывается как обычно, но что произойдет, если bar заимствует, т.е. fn bar(&self) -> ...? Имеет ли значение, является ли результат bar зависит от времени жизни &self?

То есть, foo может быть возвращение MutexGuard; важно знать, когда охранник сброшен (и мьютекс разблокирован).

Экспериментальный метод показывает, что безымянное значение отбрасывается после того, как оператор, в котором он создан, "завершен"; заставить "рано" бросить let Требуется заявление.

Детская площадка

#[derive(Debug)]
pub struct Foo;
pub fn foo() -> Foo {
    println!("foo()");
    Foo
}
impl Foo {
    pub fn bar(&self) {
    }
}
impl Drop for Foo {
    fn drop(&mut self) {
        println!("Foo::drop()");
    }
}

fn main() {
    println!("--- scope test start");
    println!("value: {:?}", foo().bar());
    println!("--- end");

    println!("--- scope test start");
    match foo().bar() {
        v => println!("value: {:?}", v),
    }
    println!("--- end");

    println!("--- scope test start");
    let v = foo().bar();
    println!("value: {:?}", v);
    println!("--- end");
}

печатает:

--- scope test start
foo()
value: ()
Foo::drop()
--- end
--- scope test start
foo()
value: ()
Foo::drop()
--- end
--- scope test start
foo()
Foo::drop()
value: ()
--- end

1 ответ

Решение

Из ссылки:

При использовании rvalue в большинстве контекстов lvalue создается временное безымянное lvalue и используется вместо него, если не повышен до 'static, Продвижение rvalue выражения к 'static слот возникает, когда выражение может быть записано в константе, заимствованной и разыменованной, которая заимствует там, где выражение было изначально написано, без изменения поведения во время выполнения. То есть продвигаемое выражение может быть оценено во время компиляции, и результирующее значение не содержит внутреннюю изменчивость или деструкторы (эти свойства определяются на основе значения, где это возможно, например, &None всегда имеет тип &'static Option<_>, так как в нем ничего не запрещено). В противном случае время жизни временных значений обычно

  • самое сокровенное заявление; хвостовое выражение блока считается частью оператора, который включает в себя блок, или

  • выражение условия или условное выражение цикла, если временное создается в выражении условия if или if/else или в цикле условного выражения while выражение.

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

Ссылка затем имеет примеры этих правил.

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