Println! 是借用还是拥有变量?

我对借贷和所有权感到困惑

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

他们说

println!可以借用 x

我对此感到困惑。如果 println!借用 x,为什么它通过 x而不是 &x

我尝试在下面运行这个代码

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

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

7341 次浏览

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) ,Display只是将它传递给 &T。你也可以写 &&&&&&&&&&&&&&&&&&&&&&&x