打印!借用或拥有变量?

Does println! borrow or own the variable?

我对借用和所有权感到困惑。在 Rust documentation about reference and borrowing

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

他们说

println! can borrow x.

我对此感到困惑。如果println!x,为什么传x而不传&x

我尝试运行下面这段代码

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

此代码与上面的代码相同,除了我将 &x 传递给 println!。它将“6”打印到控制台,这是正确的,并且与第一个代码的结果相同。

print!println!eprint!eprintln!write!writeln!format!是一个特殊情况并隐式引用任何要格式化的参数。

这些宏的行为与普通函数不同,宏为方便起见;他们默默地引用参考是这种差异的一部分。

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

运行 通过夜间编译器上的 rustc -Z unstable-options --pretty expanded,我们可以看到 println! 扩展为:

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

进一步整理,是这样的:

use std::{fmt, io};

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

注意 &x

如果你写println!("{}", &x),你就是在处理两层引用;这具有相同的结果,因为 &T 有一个 std::fmt::Display 的实现,其中 T 实现 Display(显示为 impl<'a, T> Display for &'a T where T: Display + ?Sized),它只是通过它。你也可以写 &&&&&&&&&&&&&&&&&&&&&&&x.