原文标题:Understanding Partial Moves in Rust


原文链接:https://whileydave.com/2020/11/30/understanding-partial-moves-in-rust/


公众号: Rust 碎碎念


翻译 by: Praying

最近,我一直在研究Rust,虽然从很多方面来看它都是一门十分优秀的语言,但我也发现了很多不易察觉的复杂性。其中一个例子就是,不太引人注意的局部移动(partial move) 。因此,我在想,为什么不写一篇文章来介绍它呢?

所有权(简洁版)

我不准备在这里介绍Rust中所有权和借用的全部细节。不过,这里我们仍然需要一些背景知识使得局部移动(partial move)能够讲得通。下面通过是一个box和一个箭头头来表示Rust中的所有权!

在一个没有所有权的世界里(想想Java、C/C++),我们可以通过别名(aliasing)毫无限制地引用数据。我们可以让两个引用指向相同的数据,数据之间互相引用等等。

在所有权的世界里(即Rust),一个引用可以拥有它所指向的数据。在这种情况下,不允许再有对该数据的持有所有权的其他引用(owning references)。例如,如果两个引用指向相同的数据(即上图中中间的情况),只有一个引用可以是所有者。

这种对关联所有权的引用的限制影响了我们写程序的方式。假定我们试图从变量p拷贝一份持有所有权的引用到变量q:

这就行不通了,因为它破坏了所有权的不变性 。如果允许这种情况,我们将会对同一份数据持有两个带有所有权的引用,而这是不被允许的。所以,我们该怎么办呢?我们可以移动(move)它


在上图中,变量p的值经过移动(move)操作后已经作废,在对p赋予新的值之前,我们不能再使用它了。当然,这也对我们使用Rust编写程序产生了相当大的影响。但是,我不准备在这里讨论这个问题。

局部移动(Partial Moves)

目前为止,我已经看到了一次性移动(move)整个变量(例如,上面中从p移动到q)。此外,我们还可以执行一个局部移动(partial move),在局部移动(partial move)中,可以仅移动(move)给定变量的一部分内容。假定现在我们的变量p是一个pair,其中每个元素包含一个持有所有权的引用。然后,我们可以把p中的第二个元素移动到另一个变量q中,如下图所示:

这个例子的有趣之处在于,不同于之前的情况,尽管变量p的一部分内容已经失效,但它仍然可以以一种受限的方式被使用。具体来讲,我们可以使用p.0但是不能使用p.1。此外,Rust阻止我们对变量p进行整个的拷贝(copy)或移动(move)(尽管在我看来,这并没有必要)。上面的示例转为代码,如下:

fn main() { 
    let mut x = 123;
    let mut y = 456;
    let mut p = (&mut x,&mut y);
    let mut q = p.1;
    ...
}

目前为止,一切都好。但是,当对...进行替换, 比如替换为let mut z = p;时,我们会得到下面的错误信息:

error[E0382]: use of partially moved value: `p`
 --> src/main.rs:6:17
  |
5 | let mut q = p.1;
  |             --- value partially moved here
6 | let mut z = p;
  |             ^ value used here after partial move

只是简单地告诉我们,我们不能使用一个由于之前的移动(move)操作而已经失效的值。个人而言,我不太理解为什么Rust阻止这种移动(move)操作,因为能够很容易地推导出z只是被部分定义(译注:即另一部分无效),就像它对p所做的那样。想必是,尽管可以推导,但是通过某个引用对p赋值必然会导致某些问题吧。

总结

Rust是一门相当酷的语言,但是仍然有很多微妙的特性。希望这篇文章可以帮助解答其中的一个困惑。

【译】理解Rust中的局部移动的更多相关文章

  1. 【译】理解Rust中的闭包

    原文标题:Understanding Closures in Rust 原文链接:https://medium.com/swlh/understanding-closures-in-rust-21f2 ...

  2. 【译】理解Rust中的Futures (一)

    原文标题:Understanding Futures In Rust -- Part 1 原文链接:https://www.viget.com/articles/understanding-futur ...

  3. 【译】理解Rust中的Futures(二)

    原文标题:Understanding Futures in Rust -- Part 2 原文链接:https://www.viget.com/articles/understanding-futur ...

  4. 【译】深入理解Rust中的生命周期

    原文标题:Understanding Rust Lifetimes 原文链接:https://medium.com/nearprotocol/understanding-rust-lifetimes- ...

  5. 【译】Rust中的array、vector和slice

    原文链接:https://hashrust.com/blog/arrays-vectors-and-slices-in-rust/ 原文标题:Arrays, vectors and slices in ...

  6. [NodeJs系列][译]理解NodeJs中的Event Loop、Timers以及process.nextTick()

    译者注: 为什么要翻译?其实在翻译这篇文章前,笔者有Google了一下中文翻译,看的不是很明白,所以才有自己翻译的打算,当然能力有限,文中或有错漏,欢迎指正. 文末会有几个小问题,大家不妨一起思考一下 ...

  7. 刷完欧拉计划中难度系数为5%的所有63道题,我学会了Rust中的哪些知识点?

    我为什么学Rust? 2019年6月18日,Facebook发布了数字货币Libra的技术白皮书,我也第一时间体验了一下它的智能合约编程语言MOVE,发现这个MOVE是用Rust编写的,看来想准确理解 ...

  8. [译]线程生命周期-理解Java中的线程状态

    线程生命周期-理解Java中的线程状态 在多线程编程环境下,理解线程生命周期和线程状态非常重要. 在上一篇教程中,我们已经学习了如何创建java线程:实现Runnable接口或者成为Thread的子类 ...

  9. 如何理解javaSript中函数的参数是按值传递

    本文是我基于红宝书<Javascript高级程序设计>中的第四章,4.1.3传递参数小节P70,进一步理解javaSript中函数的参数,当传递的参数是对象时的传递方式. (结合资料的个人 ...

随机推荐

  1. 辨析:IIR(Infinite Impulse Response)与FIR(Finite Impulse Response)

    IIR和FIR系统描述的是系统的抽样响应特性,其中$ x(n)=\delta(n) $ 举例:一个平均器的系统是FIR系统,因为它的抽样响应仅在变量n取某3个值的时候有值,是有限长的:一阶自回归模型由 ...

  2. SSM使用Ueditor

    富文本编辑器(UEditor) 1. 下载UEditor富文本编辑器 建议下载 utf8-jsp 版本的,结构目录如下: 下载地址:链接:https://pan.baidu.com/s/1Nq0oJB ...

  3. 快进来!花几分钟看一下 ReentrantReadWriteLock 的原理!

    前言 在看完 ReentrantLock 之后,在高并发场景下 ReentrantLock 已经足够使用,但是因为 ReentrantLock 是独占锁,同时只有一个线程可以获取该锁,而很多应用场景都 ...

  4. The Product-Minded Software Engineer

    转自The Product-Minded Software Engineer Product-minded engineers are developers with lots of interest ...

  5. z-index属性详解

    z-index属性详解 目录 z-index属性详解 一.定义和用法 二.代码 三.效果图 一.定义和用法 z-index属性指定一个元素的堆叠顺序,也就是z轴 position属性定义的是x轴和y轴 ...

  6. .net 实现之短信验证码

    接口类型:互亿无线触发短信接口,支持发送验证码短信.订单通知短信等. 账户注册:请通过该地址开通账户http://sms.ihuyi.com/register.html 只能测试用: 实现注册页面 & ...

  7. [阿里DIN] 从模型源码梳理TensorFlow的乘法相关概念

    [阿里DIN] 从模型源码梳理TensorFlow的乘法相关概念 目录 [阿里DIN] 从模型源码梳理TensorFlow的乘法相关概念 0x00 摘要 0x01 矩阵乘积 1.1 matmul pr ...

  8. 阿里云函数计算 VSCode 使用,及部署 Docusaurus

    代码: https://github.com/ikuokuo/start-serverless 使用简介 产品页开通服务.使用流程,如下: 新手示例,如下: 创建函数 阿里云提供了如下几种方式创建函数 ...

  9. python_udp_多人聊天室_简单版

    udp-一定是client端先发送数据. server.py import socket friend_lst = {'alex':'32','太白':'33'} sk =socket.socket( ...

  10. CSS渐变中是如何定义渐变线的

    在CSS语法中用户代理对渐变gradient语法的解析渲染离不开渐变线.渐变分为线性渐变(linear gradient)和径向渐变(radial gradient). 渐变在元素盒模型中backgr ...