给定一个函数foo
它采用对切片的可变引用。它可以减少切片的长度a = &mut a[1..]
。但是,我一直无法弄清楚如何编写一个变异的函数a
以同样的方式。
fn foo(mut a: &mut [i32]) {
a = &mut a[1..];
inc(&mut a);
}
fn inc<'a: 'b, 'b>(s: &'b mut &'a mut [i32]) {
*s = &mut s[1..];
}
inc
是编写这样一个函数的尝试。但是,它失败了:
Output of rustc nightly (Compiler #1)
error[E0623]: lifetime mismatch
--> <source>:3:9
|
2 | fn inc<'a: 'b, 'b>(s: &'b mut &'a mut [i32]) {
| ---------------------
| |
| these two types are declared with different lifetimes...
3 | *s = &mut s[1..];
| ^^^^^^^^^^^ ...but data from `s` flows into `s` here
错误的一个更简单的例子是
fn oops<'a: 'b, 'b>(a: &'b mut &'a mut i32) {
let _: &'a mut i32 = *a; // error!
}
这里的问题是有a
(对某些数据的可变引用)让您mutate(改变)它指向的值,但它不让你move值(不留下任何东西)。在oops
,因为一次只能对任何事物有一个可变引用,*a
需要移至_
,但这留下了*a
没有数据和a
指向“垃圾”。但无论是谁借的*a
to oops
期望*a
返回时具有价值,因此必须禁止这样做。 (我说“垃圾”是因为这个举动可能并没有真正变异*a
,如果我们强制执行它可能不会出错。但如果我们不关心性能,此举原则上可能会破坏*a
强制执行“一次可变借用”规则,在这种情况下你就会被淘汰。)
就你而言,index_mut
(正在实施[1..]
语法)需要&mut [i32]
, so *s
需要移动到函数中。但这留下了*s
没有价值,你也不拥有*s
,这是非法的。你最终会收回价值并不重要。例如。如果index_mut
恐慌,调用者将期望它借给的任何变量有一个值inc
,但不会有任何。相比之下,foo
does own a
,所以离开也没关系a
持续时间内无价值index_mut
in a = &mut a[1..]
(编译器可以跟踪拥有的变量何时有值和没有值)。
一种解决方法(不更改界面)是将默认值粘贴到*s
当你对其进行操作时。这impl<'a, T> Default for &'a mut[T]
提供这个(默认值指向一个空切片),并且std::mem::take
包那Default
以安全的方式实施。
fn inc<'a: 'b, 'b>(s: &'b mut &'a mut [i32]) {
*s = &mut std::mem::take(s)[1..];
}
我同意@cdhowie 的写作
fn inc<'a>(s: &'a mut [i32]) -> &'a mut [i32] {
return s[1..];
}
并要求使用a = inc(a)
是一个比inc(&mut a)
界面。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)