如果不允许同时使用两个可变引用,为什么允许它们呢?

Pun*_*y64 2 rust

根据文档,

\n
\n

数据竞争会导致未定义的行为,并且当您\xe2\x80\x99尝试在运行时追踪它们时,可能很难诊断和修复;Rust 通过拒绝编译带有数据竞争的代码来防止这个问题!

\n
\n

除非你\xe2\x80\x99re多线程,否则为什么这是一个问题?如果同时访问一个变量及其一个mut引用,\xe2\x80\x99t 这个问题是否仍然存在?

\n

cdh*_*wie 9

你似乎对某些事情感到困惑。

\n

首先,您似乎有这样的印象:如果您可变地借用一个值,则可以通过可变引用并直接使用您借用的变量来改变该值。 这不是真的。 在借用结束之前,该变量实际上不可用:

\n
fn main() {\n    let mut x = 0;\n    let y = &mut x;\n\n    // The following line causes a compile-time error.\n    // error[E0506]: cannot assign to `x` because it is borrowed\n    x = 1;\n\n    *y = 2;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

最多可以有一个名称,通过该名称可以在任何给定时刻修改值。由于x被 可变地借用y,因此在借用者被释放之前,该名称x不能用于修改值y

\n
\n

除非你\xe2\x80\x99re多线程,否则为什么这是一个问题?

\n
\n

因为改变状态可能会使引用无效。

\n

考虑一下您有 Vec 的情况。当 Vec 或其任何元素被借用时,您不得修改 Vec 或其任何内容,因为这是不安全的。为什么在单线程代码中会不安全?

\n

如果您引用了某个项目并且该项目从 Vec 中删除了,会发生什么情况?您引用了无效值或与之前不同的值。

\n

如果向 Vec 添加一个元素,但其内部数组已满,会发生什么情况?Vec 将分配一个新的、较大的数组,将较小数组中的所有元素转移到较大数组中,然后销毁较小数组。 所有先前存在的对元素的引用都将因该操作而失效。

\n

这就是为什么你不能在迭代 Vec 时改变它,例如:

\n
for item in some_vec.iter() {\n    some_vec.push(item.clone());\n}\n
Run Code Online (Sandbox Code Playgroud)\n

Vec::push()需要可变地借用 Vec,但迭代需要不变地借用 Vec。你不能同时做这两件事。

\n

Rust 不允许你做这些事情,因为它们从根本上来说是不健全的操作。Rust 语言的全部目的是在编译时准确捕获此类问题。

\n

请注意,这在 C++ 中也是不安全的,例如,向 an 添加元素std::vector 可能会使所有现有引用无效(在重新分配的情况下),当您尝试使用无效引用时,这可能会导致未定义的行为。

\n

不同的是C++会接受这个危险的代码。在 C++ 中,检查内存安全是程序员的工作,如果搞砸了,就会出现潜在的灾难性错误,甚至是严重的安全漏洞。

\n

这就是 Rust 被创建的原因——承担人类不擅长的这项关键任务,并让编译器为你完成它。

\n

  • 我发现 [C++ `std::vector` 迭代器失效表](https://en.cppreference.com/w/cpp/container/vector) 有点滑稽,以一种令人沮丧的方式。“这里列出了通过编写看起来完全正常、无错误的代码来调用 UB 的方法!” (5认同)
  • @trent“但我足够聪明,可以正确使用它。” - 在创建 CVSS 10.0 漏洞之前所说的。 (5认同)