如何在 'Option' 中多次访问一个向量?
How to access a vector multiple times within an 'Option'?
如何在 Rust 第一次访问时不移动它的情况下访问选项中的向量?
fn maybe_push(v_option: Option<&mut Vec<usize>>) -> usize {
let mut c = 0;
if let Some(v) = v_option {
for i in 0..10 {
v.push(i);
c += i;
}
} else {
for i in 0..10 {
c += i;
}
}
// second access, fails
if let Some(v) = v_option {
for i in 10..20 {
v.push(i);
c += i;
}
} else {
for i in 10..20 {
c += i;
}
}
return c;
}
fn main() {
let mut v: Vec<usize> = vec![];
println!("{}", maybe_push(Some(&mut v)));
println!("{}", maybe_push(None));
println!("{:?}", v);
}
这给出了错误:
error[E0382]: use of partially moved value: `v_option`
--> src/main.rs:16:22
|
4 | if let Some(v) = v_option {
| - value moved here
...
16 | if let Some(v) = v_option {
| ^^^^^^^^ value used here after move
使用建议的 if let Some(ref mut v) = v_option {
也失败了:
error: cannot borrow immutable anonymous field `(v_option:std::prelude::v1::Some).0` as mutable
--> src/main.rs:4:21
|
4 | if let Some(ref mut v) = v_option {
| ^^^^^^^^^
error: cannot borrow immutable anonymous field `(v_option:std::prelude::v1::Some).0` as mutable
--> src/main.rs:17:21
|
17 | if let Some(ref mut v) = v_option {
| ^^^^^^^^^
按值匹配将值移动到模式变量中。移动会使原始值不可用,除了实现 Copy
特征的非常简单的对象,例如数字。与 C 中的指针不同,可变引用是不可复制的,这可以在以下也无法编译的示例中看出:
let mut v = vec![1, 2, 3];
let rv = &mut v; // mutable reference to v
{
// move rv to r1, r1 now becomes the sole mutable reference to v
let r1 = rv;
r1.push(4);
}
{
let r2 = rv; // error: rv was already moved to r1
r2.push(5);
}
Rust 拒绝上述内容,因为它强制执行禁止对一个对象的多个可变引用的一般规则。尽管这个特定的代码片段是安全的,但同时允许对同一对象的多个可变引用将使编写 Rust 明确设计要防止的那种不安全程序变得容易,例如那些在多线程代码中包含数据竞争的,或者那些通过无效迭代器访问数据的。因此赋值 let r1 = rv
只能 移动 rv
对 r1
的引用,不允许 let r2 = rv
语句现在引用移动的变量 rv
.
要修复代码,我们必须创建对引用的单独引用。这将创建两个对原始引用的不同可变引用,而不是将原始可变引用移动到内部范围:
let mut v = vec![1, 2, 3];
let mut rv = &mut v;
{
// rr1 is a *new* mutable reference to rv - no move is performed
let rr1 = &mut rv;
rr1.push(4);
}
{
// rr2 is a *separate* new mutable reference to rv - also no move
let rr2 = &mut rv;
rr2.push(5);
}
push
调用的语法与 r1.push
和 rr1.push
相同,因为 Rust 的 .
运算符将自动解引用任意数量的引用。
至 return 至问题示例,Option
中对 Vec<usize>
的引用类似于上面的 v
引用,并使用 Some(v)
pattern 将引用移动到 v
pattern 变量中。
要修复它,必须像上面的示例一样更改模式,以指定一个变量,该变量 引用 本身就是引用的值。这是使用 if let Some(ref mut v)
语法实现的。如上所述,rv
声明必须更改为可变的,此修复还要求 Option
是可变的。通过这两个更改,代码编译:
fn maybe_push(mut v_option: Option<&mut Vec<usize>>) -> usize {
let mut c = 0;
if let Some(ref mut v) = v_option {
for i in 0..10 {
v.push(i);
c += i;
}
} else {
for i in 0..10 {
c += i;
}
}
if let Some(ref mut v) = v_option {
for i in 10..20 {
v.push(i);
c += i;
}
} else {
for i in 10..20 {
c += i;
}
}
return c;
}
fn main() {
let mut v: Vec<usize> = vec![];
println!("{}", maybe_push(Some(&mut v)));
println!("{}", maybe_push(None));
println!("{:?}", v);
}
另一种可能性是使用as_mut()
方法将选项内容return作为对先前内容的可变引用。这在概念上等同于第一个代码段中从 let r1 = rv
到 let rr1 = &mut rv
的更改,并且将允许使用 if let Some(v)
模式,其中 v
仍然是对可变的引用对向量的引用。这也需要将 v_option
声明为可变的。
如何在 Rust 第一次访问时不移动它的情况下访问选项中的向量?
fn maybe_push(v_option: Option<&mut Vec<usize>>) -> usize {
let mut c = 0;
if let Some(v) = v_option {
for i in 0..10 {
v.push(i);
c += i;
}
} else {
for i in 0..10 {
c += i;
}
}
// second access, fails
if let Some(v) = v_option {
for i in 10..20 {
v.push(i);
c += i;
}
} else {
for i in 10..20 {
c += i;
}
}
return c;
}
fn main() {
let mut v: Vec<usize> = vec![];
println!("{}", maybe_push(Some(&mut v)));
println!("{}", maybe_push(None));
println!("{:?}", v);
}
这给出了错误:
error[E0382]: use of partially moved value: `v_option`
--> src/main.rs:16:22
|
4 | if let Some(v) = v_option {
| - value moved here
...
16 | if let Some(v) = v_option {
| ^^^^^^^^ value used here after move
使用建议的 if let Some(ref mut v) = v_option {
也失败了:
error: cannot borrow immutable anonymous field `(v_option:std::prelude::v1::Some).0` as mutable
--> src/main.rs:4:21
|
4 | if let Some(ref mut v) = v_option {
| ^^^^^^^^^
error: cannot borrow immutable anonymous field `(v_option:std::prelude::v1::Some).0` as mutable
--> src/main.rs:17:21
|
17 | if let Some(ref mut v) = v_option {
| ^^^^^^^^^
按值匹配将值移动到模式变量中。移动会使原始值不可用,除了实现 Copy
特征的非常简单的对象,例如数字。与 C 中的指针不同,可变引用是不可复制的,这可以在以下也无法编译的示例中看出:
let mut v = vec![1, 2, 3];
let rv = &mut v; // mutable reference to v
{
// move rv to r1, r1 now becomes the sole mutable reference to v
let r1 = rv;
r1.push(4);
}
{
let r2 = rv; // error: rv was already moved to r1
r2.push(5);
}
Rust 拒绝上述内容,因为它强制执行禁止对一个对象的多个可变引用的一般规则。尽管这个特定的代码片段是安全的,但同时允许对同一对象的多个可变引用将使编写 Rust 明确设计要防止的那种不安全程序变得容易,例如那些在多线程代码中包含数据竞争的,或者那些通过无效迭代器访问数据的。因此赋值 let r1 = rv
只能 移动 rv
对 r1
的引用,不允许 let r2 = rv
语句现在引用移动的变量 rv
.
要修复代码,我们必须创建对引用的单独引用。这将创建两个对原始引用的不同可变引用,而不是将原始可变引用移动到内部范围:
let mut v = vec![1, 2, 3];
let mut rv = &mut v;
{
// rr1 is a *new* mutable reference to rv - no move is performed
let rr1 = &mut rv;
rr1.push(4);
}
{
// rr2 is a *separate* new mutable reference to rv - also no move
let rr2 = &mut rv;
rr2.push(5);
}
push
调用的语法与 r1.push
和 rr1.push
相同,因为 Rust 的 .
运算符将自动解引用任意数量的引用。
至 return 至问题示例,Option
中对 Vec<usize>
的引用类似于上面的 v
引用,并使用 Some(v)
pattern 将引用移动到 v
pattern 变量中。
要修复它,必须像上面的示例一样更改模式,以指定一个变量,该变量 引用 本身就是引用的值。这是使用 if let Some(ref mut v)
语法实现的。如上所述,rv
声明必须更改为可变的,此修复还要求 Option
是可变的。通过这两个更改,代码编译:
fn maybe_push(mut v_option: Option<&mut Vec<usize>>) -> usize {
let mut c = 0;
if let Some(ref mut v) = v_option {
for i in 0..10 {
v.push(i);
c += i;
}
} else {
for i in 0..10 {
c += i;
}
}
if let Some(ref mut v) = v_option {
for i in 10..20 {
v.push(i);
c += i;
}
} else {
for i in 10..20 {
c += i;
}
}
return c;
}
fn main() {
let mut v: Vec<usize> = vec![];
println!("{}", maybe_push(Some(&mut v)));
println!("{}", maybe_push(None));
println!("{:?}", v);
}
另一种可能性是使用as_mut()
方法将选项内容return作为对先前内容的可变引用。这在概念上等同于第一个代码段中从 let r1 = rv
到 let rr1 = &mut rv
的更改,并且将允许使用 if let Some(v)
模式,其中 v
仍然是对可变的引用对向量的引用。这也需要将 v_option
声明为可变的。