为什么Rust阻止了多个可变引用? [英] Why Rust prevents from multiple mutable references?

查看:530
本文介绍了为什么Rust阻止了多个可变引用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

与该主题一样,Rust为什么阻止多个可变引用?我已经阅读了rust-book上的章节,并且我了解到,当我们拥有多线程代码时,我们就可以避免数据竞争,但是让我们看看下面的代码:

Like in the topic, why Rust prevents from multiple mutable references? I have read chapter in rust-book, and I understand that when we have multi-threaded code we are secured from data races but let's look at this code:

fn main() {
    let mut x1 = String::from("hello");
    let r1 = &mut x1;
    let r2 = &mut x1;

    r1.insert(0, 'w');

}

此代码无法同时运行,因此无法进行数据争用. 当我创建新线程并且要在新线程中使用父线程中的变量时,还需要移动它,因此只有新线程才是父变量的所有者.

This code is not running simultaneously so there is no possibility for data races. What is more when I am creating new thread and I want to use variable from parent thread in a new thread I have to move it so only new thread is an owner of the parent variable.

我能看到的唯一原因是,程序员在成长过程中可能会迷失自己的代码.我们在多个地方可以修改一个数据,即使代码不是并行运行,我们也会出现一些错误.

The only reason I can see is that programmer can lose himself in his code when it is growing up. We have multiple places in which one piece of data can be modified and even the code is not running parallel we can get some bugs.

推荐答案

Rust同时阻止两个可变引用以防止数据竞争的事实是一个普遍的误解.这只是原因之一.防止使用两个可变的引用,可以轻松地在类型上保留不变式,并使编译器强制不违反不变式.

The fact that Rust prevent two mutable references at the same time to prevent data races is a common misconception. This is only one of the reasons. Preventing two mutable references makes it possible to keep invariants on types easily and let the compiler enforce that the invariant are not violated.

以C ++代码的平静为例:

Take this peace of C++ code for an example:

#include <vector>

int main() {
    std::vector<int> foo = { 1, 2, 3 };

    for (auto& e: foo) {
        if (e % 2 == 0) {
            foo.push_back(e+1);
        }
    }

    return 0;
}

这是不安全的,因为您不能在迭代向量时对其进行突变.修改向量可能会重新分配其内部缓冲区,这会使所有引用无效.在C ++中,这是一个UB.在Python,Java或C#(可能还有大多数其他语言)中,您会遇到运行时异常.

This is unsafe because you cannot mutate a vector while you are iterating it. Mutating the vector might reallocate its internal buffer, which invalidates all references. In C++, this is a UB. In Python, Java or C# (and probably most other languages), you would get a runtime exception.

但是,Rust可以在编译时防止此类问题:

Rust however, prevents this kind of issues at compile time:

fn main() {
    let mut foo = vec![1, 2, 3];

    for e in foo {
        if e % 2 == 0 {
            foo.push(e+1);
        }
    }
}

出现错误:

error[E0382]: borrow of moved value: `foo`
 --> src/main.rs:6:13
  |
2 |     let mut foo = vec![1, 2, 3];
  |         ------- move occurs because `foo` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
3 |     
4 |     for e in foo {
  |              ---
  |              |
  |              value moved here
  |              help: consider borrowing to avoid moving into the for loop: `&foo`
5 |         if e % 2 == 0 {
6 |             foo.push(e+1);
  |             ^^^ value borrowed here after move

这篇关于为什么Rust阻止了多个可变引用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆