专栏首页TensorFlow从0到N + Rust为什么Rust的println!不会发生所有权转移?

为什么Rust的println!不会发生所有权转移?

macro

println!可能是学习Rust最常用的一行代码了。我们连续多次调用它,下面的代码编译通过,再正常不过了。

let x = String::from("Hello!");
println!("{}", x);
println!("{}", x);

Hello! Hello!

可是,我们明明传的是x,并非&x,为什么没有发生所有权转移呢?

查查标准库的源码,如下:

#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable(print_internals, format_args_nl)]
macro_rules! println {
 () => ($crate::print!("\n"));
 ($($arg:tt)*) => ({
 $crate::io::_print($crate::format_args_nl!($($arg)*));
 })
}
​
#[unstable(
 feature = "format_args_nl",
 issue = "none",
 reason = "`format_args_nl` is only for internal \
 language use and is subject to change"
 )]
#[allow_internal_unstable(fmt_internals)]
#[rustc_builtin_macro]
#[macro_export]
macro_rules! format_args_nl {
 ($fmt:expr) => {{ /* compiler built-in */ }};
 ($fmt:expr, $($args:tt)*) => {{ /* compiler built-in */ }};
}

更让人眼花缭乱了,就算啃得动Rust宏,啃到最后那句“compiler built-in”,也足以让人崩溃。还是换个思路。

所谓“元编程”的Rust宏,是在编译期进行展开,那如果能看到展开后的Rust代码,可读性就好很多了。

对于Rust,想看宏展开后的代码,当然不是问题,真要夸夸Rust的工具链了,非常周到。唯一一个要求,就是需要切换到Rust Nightly版本。

先从安装开始。

> rustup toolchain install nightly

装好后可以看到默认是Stable版本。

> rustup toolchain list stable-x86_64-pc-windows-msvc (default) beta-x86_64-pc-windows-msvc nightly-x86_64-pc-windows-msvc

从Stable切换到Nightly也非常简单。

> cd ~/projects/print > rustup override set nightly

万事具备,进行展开,输入:

> rustc --pretty expanded -Z unstable-options main.rs

#![feature(prelude_import)]
#![no_std]
#[prelude_import]
use ::std::prelude::v1::*;
#[macro_use]
extern crate std;
fn main() {
 let x = String::from("Hello!");
 {
 ::std::io::_print(::core::fmt::Arguments::new_v1(&["", "\n"],
 &match (&x,) {
 (arg0,) => [::core::fmt::ArgumentV1::new(arg0,::core::fmt::Display::fmt)],
 }));
 };
}

此时,在终端里会打印出将宏展开后的代码,如果拷贝覆盖粘贴进main.rs,一样是可以编译通过并运行的。

说到这里,关于问题的答案也已明了,展开代码显示:println!实际生成的代码使用了&x,不可变借用

最后,记得切回Stable:

> rustup override set stable

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 回撸Rust China Conf 2020 之《浅谈Rust在算法题和竞赛中的应用》

    刚刚结束的首届Rust China Conf 2020就是一种交流学习的方式。Rust中文社区采用直播并提供视频回放,为所有Rustacean提供了绝佳的、宝贵...

    袁承兴
  • 讨厌算法的程序员 0 - 前言

    这个主题是写给自己的,假如你刚好也和我一样讨厌算法,那也是写给你的。我的主要参考书目是《算法导论》第3版中文版,自己先琢磨明白一个算法,然后再按我的理解写出来...

    袁承兴
  • 讨厌算法的程序员 3 - 算法分析基础

    ? 时间资源 上一篇,我们知道了如何用循环不变式来证明算法的正确性,本篇来看另一个重要方面:算法分析。分析算法的目的,是预测算法所需要的资源。资源不仅是指内存...

    袁承兴
  • Go进阶19:如何开发多彩动感的终端UI应用

    终端(Terminal)是计算机系统的输入输出设备,由于历史的原因终端这个概念非常混乱, 终端的发展经历了字符终端、图形终端 和 网络终端 三个阶段.

    mojocn
  • Service插件化解决方案

    1.ActivityThread最终是通过Instrumentation启动一个Activity的。而ActivityThread启动Service并不借助于I...

    用户3112896
  • 【iOS】一些微信提示音

    收集了一些微信提示音并把它做成了网站,支持试听(github搭建的,可能点试听会有点延迟)

    zby1101
  • POJ-3744-Scout YYF I

    ACM模版 描述 ? 题解 image.png 代码 #include <iostream> #include <algorithm> #include <cs...

    f_zyj
  • 企业支付宝账号开发接口教程--JAVA-UTF-8(实际操作------SpringMVC+JSP)

    关于即时到账的开发。审核通过。简单测试如下。 希望看的可以收藏或者赞一下哦。 1:拥有自己的支付宝企业账号。去产品商店选择适合自己的方案。并签约合同。 ? 2:...

    小帅丶
  • Java web项目如何获取某个文件夹下面的文件路径 绝对路径 ?

    爱明依
  • Go 错误处理

    Go 语言通过内置的错误接口提供了非常简单的错误处理机制。 error类型是一个接口类型,这是它的定义: type error interface { ...

    李海彬

扫码关注云+社区

领取腾讯云代金券