println!借用或拥有变量?

kev*_*nyu 39 ownership rust

我对借贷和所有权感到困惑.在Rust 文档中有关引用和借用的内容

let mut x = 5;
{
    let y = &mut x;
    *y += 1;
}
println!("{}", x);
Run Code Online (Sandbox Code Playgroud)

他们说

println!可以借x.

我很困惑.如果println!借入x,为什么它通过x&x

我尝试在下面运行此代码

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

除了传递&x给代码之外,这段代码与上面的代码相同println!.它将'6'打印到控制台,这是正确的,与第一个代码的结果相同.

Chr*_*gan 43

print!,println!,eprint!,eprintln!,write!,writeln!format!是一个特例,而不是表现为正常的事情,为方便做的原因.他们默默地参考的事实是这种差异的一部分.

fn main() {
    let x = 5;
    println!("{}", x);
}
Run Code Online (Sandbox Code Playgroud)

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),
                ]
            }
        },
    ));
}
Run Code Online (Sandbox Code Playgroud)

整理了很多,就是这样:

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)],
    ));
}
Run Code Online (Sandbox Code Playgroud)

请注意&x.

如果你写println!("{}", &x),那么你正在处理两个级别的引用; 此具有相同的结果,因为存在的实施方案std::fmt::Display&T,其中T工具Display(示为impl<'a, T> Display for &'a T where T: Display + ?Sized),其只是使其通过.你也可以写&&&&&&&&&&&&&&&&&&&&&&&x.

  • 也许书上可以指出这一点?也让我很困惑。 (11认同)
  • @MarkusUnterwaditzer:当然,但问题是看起来很正常但不是.当然,其他宏也可以使自己成为特殊情况.事实是,一般来说,强烈建议不要这样做. (8认同)
  • 我不明白您为什么将这些宏称为“特殊情况”。可以为任何宏实现这种隐式引用传递。 (2认同)