首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么Rust阻止多个可变引用?

为什么Rust阻止多个可变引用?
EN

Stack Overflow用户
提问于 2019-10-13 23:03:37
回答 1查看 1.7K关注 0票数 11

就像主题中的,为什么Rust阻止了多个可变引用?我已经读过rust-book中的章节,我知道当我们有多线程代码时,我们可以避免数据竞争,但让我们看看下面的代码:

代码语言:javascript
复制
fn main() {
    let mut x1 = String::from("hello");
    let r1 = &mut x1;
    let r2 = &mut x1;

    r1.insert(0, 'w');

}

此代码不是同时运行的,因此不存在数据竞争的可能性。更重要的是,当我创建新线程时,我想在新线程中使用来自父线程的变量,我必须移动它,这样只有新线程才是父变量的所有者。

我能看到的唯一原因是,程序员在成长过程中可能会沉浸在代码中。我们有多个地方可以修改一段数据,即使代码不是并行运行的,我们也会得到一些错误。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-10-13 23:28:47

Rust同时阻止两个可变引用以防止数据竞争的事实是一个常见的误解。这只是其中一个原因。通过防止两个可变引用,可以轻松地在类型上保留不变量,并让编译器强制不违反不变量。

以下面这段C++代码为例:

代码语言:javascript
复制
#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# (可能还有大多数其他语言)中,您会得到一个运行时异常。

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

代码语言:javascript
复制
fn main() {
    let mut foo = vec![1, 2, 3];
    
    for e in foo {
        if e % 2 == 0 {
            foo.push(e+1);
        }
    }
}

给出一个错误:

代码语言:javascript
复制
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
票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58364807

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档