Rust 的 println! 怎么样?宏执行解除引用? [重复]

问题描述 投票:0回答:1

println!
宏可以处理值和引用,而不需要显式取消引用。

首先,创建一个向量

let v = vec![0, 2, 3, -4];
  1. 打印来自

    vec.iter

    的参考资料
    for x in v.iter() {
        println!("x: {}", x);
    }
    
  2. vec.iter

    打印取消引用的元素
    for x in v.iter() {
        println!("x: {}", *x);
    }
    
  3. 打印来自

    vec

    的值
    for x in v {
        println!("x: {}", x);
    }
    

案例1中的内部解除引用是如何完成的?

我在内部知道

println!
进行了另一个宏调用,但链中的最后一个宏
format_args!
是在编译器级别实现的,我对此没有任何看法。

macro_rules! println {
    ($fmt:expr) => (print!(concat!($fmt, "\n")));
    ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*));
}

macro_rules! print {
    ($($arg:tt)*) => ($crate::io::_print(format_args!($($arg)*)));
}

macro_rules! format_args {
    ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ })
}

源码参考

macros rust dereference
1个回答
4
投票

这里重要的是,在格式字符串中使用

{}
会调用传递值的
Display
特征。

正如预期的那样,i32 类型实现了

Display
,这使得您的案例#2 和案例#3 能够工作。因为他们得到的是标准
i32
值,而不是参考值,所以一切都有效。

对于你的案例#1,

x
将是
&i32
,这似乎是你问题的核心。答案就在
Display
特质
中。显示屏包含以下内容:

impl<'a, T> Display for &'a T 
where
    T: Display + ?Sized

表示“对于

T
的引用类型,如果
Display
实现了
T
,则实现
Display
”。这意味着因为
i32
实现了
Display
,所以引用类型也会自动实现它。

编译器在这里没有进行特殊的类型处理。编译器实现的代码将该责任传递给

Display
特征的实现。

© www.soinside.com 2019 - 2024. All rights reserved.