【问题标题】:Does println! borrow or own the variable?打印!借用还是拥有变量?
【发布时间】:2015-08-07 15:30:43
【问题描述】:

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

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' 是正确的,并且与第一个代码的结果相同。

【问题讨论】:

    标签: rust ownership


    【解决方案1】:

    宏 print!、println!、eprint!、eprintln!、write!、writeln! 和 format! 是一种特殊情况,它们隐式引用任何要格式化的参数。

    为了方便起见,这些宏不像普通函数和宏那样工作;他们默默地引用引用的事实是这种差异的一部分。

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

    在 nightly 编译器上通过 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。

    【讨论】:

    • 我不明白您为什么将这些宏称为“特殊情况”。这种隐式引用传递可以为任何宏实现。
    • @MarkusUnterwaditzer:当然,但问题是它看起来很正常,但实际上并非如此。当然,其他宏也可以使自己成为特殊情况。事实上,一般情况下强烈建议不要这样做。
    • 也许这可以在书中指出?也让我很困惑。
    猜你喜欢
    • 2015-08-12
    • 1970-01-01
    • 1970-01-01
    • 2017-02-11
    • 2011-09-09
    • 1970-01-01
    • 2022-11-26
    • 2022-11-22
    相关资源
    最近更新 更多