Ответ 1
Макросы print!
, println!
, eprint!
, eprintln!
, write!
, writeln!
и format!
- это особый случай, который не ведет себя так, как обычно, по соображениям удобства. Тот факт, что они берут ссылки молча, является частью этой разницы.
fn main() {
let x = 5;
println!("{}", x);
}
Запустите его через 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),
]
}
},
));
}
Успокойно, вот это:
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)],
));
}
Обратите внимание на &x
.
Если вы пишете println!("{}", &x)
, вы тогда имеете дело с двумя уровнями ссылок; это имеет тот же результат, потому что существует реализация std::fmt::Display
для &T
, где T
реализует Display
(показано как impl<'a, T> Display for &'a T where T: Display + ?Sized
), который просто проходит его. Вы также можете написать &&&&&&&&&&&&&&&&&&&&&&&x
.