我对借用和所有权感到困惑。在 rust 中documentation about reference and borrowing
let mut x = 5;
{
let y = &mut x;
*y += 1;
}
println!("{}", x);
他们说
println!
can borrowx
.
我对此感到困惑。如果 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)
,然后您将处理两个级别的引用;这具有相同的结果,因为存在 std::fmt::Display
的实现对于 &T
其中 T
工具 Display
(显示为 impl<'a, T> Display for &'a T where T: Display + ?Sized
)刚刚通过它。你也可以写 &&&&&&&&&&&&&&&&&&&&&&&x
.
2023 年初更新:
自 2021 年年中以来,所需的调用一直是
rustc -Zunpretty=expanded
而不是rustc -Zunstable-options --pretty=expanded
.自 2023 年 1 月 28 日左右开始 ( https://github.com/rust-lang/rust/pull/106745 ),
format_args!
是 AST 的一部分,因此println!("{}", x)
的扩展是::std::io::_print(format_args!("{0}\n", x));
, 不暴露Arguments::new_v1
建筑和&x
方面。出于各种原因这很好(阅读 #106745’s description ),但破坏了我在这里的清晰演示x
仅供引用。 (这就是为什么我在末尾将其添加为注释而不是更新答案的原因——因为它不再有效。)
关于rust - 打印!借用或拥有变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30450399/