zoukankan      html  css  js  c++  java
  • 【译】理解Rust中的局部移动

    原文标题: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是一门相当酷的语言,但是仍然有很多微妙的特性。希望这篇文章可以帮助解答其中的一个困惑。

  • 相关阅读:
    efwplus框架
    注册区域
    社招面试记录与总结
    验证码 Captcha 之大插件
    发生内存泄漏?
    Flume+LOG4J+Kafka
    协议如何保证可靠传输
    oracle之spool详细使用总结(转)
    SSH协议详解(转)
    oracle nologging用法(转)
  • 原文地址:https://www.cnblogs.com/praying/p/14072821.html
Copyright © 2011-2022 走看看