本文介绍了是否 println!借用或拥有变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am confused with borrowing and ownership. In the Rust documentation about reference and borrowing

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

他们说

println! 可以借用x.

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

I am confused by this. If println! borrows x, why does it pass x not &x?

我尝试在下面运行此代码

I try to run this code below

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

此代码与上面的代码相同,只是我将 &x 传递给 println!.它向控制台打印6",这是正确的并且与第一个代码的结果相同.

This code is identical with the code above except I pass &x to println!. It prints '6' to the console which is correct and is the same result as the first code.

推荐答案

print!, println!, eprint!, eprintln!write!writeln!format! 是特殊情况,隐式地引用任何参数进行格式化.

The macros print!, println!, eprint!, eprintln!, write!, writeln! and format! are a special case and implicitly take a reference to any arguments to be formatted.

为了方便起见,这些宏的行为不像普通函数和宏;他们默默地接受引用的事实是这种差异的一部分.

These macros do not behave as normal functions and macros do for reasons of convenience; the fact that they take references silently is part of that difference.

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

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

Run it through rustc -Z unstable-options --pretty expanded on the nightly compiler and we can see what println! expands to:

#![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,
                )],
            },
        ));
    };
}

进一步整理,是这样的:

Tidied further, it’s this:

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),那么你就是在处理两层引用;这具有相同的结果,因为有一个 std:: 的实现fmt::Display 用于 &T 其中 T 实现 Display(显示为 impl<'a, T> Display for &'a T where T: Display + ?Sized) 刚刚通过它.你也可以写 &&&&&&&&&&&&&&&&&&&;&&x.

If you write println!("{}", &x), you are then dealing with two levels of references; this has the same result because there is an implementation of std::fmt::Display for &T where T implements Display (shown as impl<'a, T> Display for &'a T where T: Display + ?Sized) which just passes it through. You could just as well write &&&&&&&&&&&&&&&&&&&&&&&x.

这篇关于是否 println!借用或拥有变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-21 13:02