Подтвердить что ты не робот

Печатает! заимствовать или владеть переменной?

Я путаюсь с заимствованием и владением. В документации Rust о ссылках и заимствованиях

let mut x = 5;
{
    let y = &mut x;
    *y += 1;
}
println!("{}", x);

Говорят,

println! может брать x.

Я смущен этим. Если println! занимает x, почему он передает 'x' not '& x'?

Я пытаюсь запустить этот код ниже

fn main() {
    let mut x = 5;
    {
        let y = &mut x;
        *y += 1;
    }
    println!("{}", &x);
}

Этот код идентичен приведенному выше коду, за исключением того, что я передаю '& x' в println!. Он выводит "6" на консоль, что является правильным и является тем же результатом, что и первый код.

4b9b3361

Ответ 1

Макросы print!, println!, eprint!, eprintln!, write!, writeln! и format! - это особый случай, который не ведет себя так, как обычно, по соображениям удобства. Тот факт, что они берут ссылки молча, является частью этой разницы.

fn main() {
    let x = 5;
    println!("{}", x);
}

Запустите его через rustc -Z unstable-options --pretty expanded в ночном компиляторе, и мы увидим, что println! расширяет:

#![feature(prelude_import)]
#![no_std]
#[prelude_import]
use std::prelude::v1::*;
#[macro_use]
extern crate std as std;
fn main() {
    let x = 5;
    ::io::_print(::std::fmt::Arguments::new_v1(
        {
            static __STATIC_FMTSTR: &'static [&'static str] = &["", "\n"];
            __STATIC_FMTSTR
        },
        &match (&x,) {
            (__arg0,) => {
                [
                    ::std::fmt::ArgumentV1::new(__arg0, ::std::fmt::Display::fmt),
                ]
            }
        },
    ));
}

Успокойно, вот это:

use std::fmt;
use std::io;

fn main() {
    let x = 5;
    io::_print(fmt::Arguments::new_v1(
        &["", "\n"];
        &[fmt::ArgumentV1::new(&x, fmt::Display::fmt)],
    ));
}

Обратите внимание на &x.

Если вы пишете println!("{}", &x), вы тогда имеете дело с двумя уровнями ссылок; это имеет тот же результат, потому что существует реализация std::fmt::Display для &T, где T реализует Display (показано как impl<'a, T> Display for &'a T where T: Display + ?Sized), который просто проходит его. Вы также можете написать &&&&&&&&&&&&&&&&&&&&&&&x.