此问题在此处已有答案:
Temporarily move out of borrowed content(3个答案)
11天前关闭
截至10天前,社区正在审查是否重新讨论这个问题。
我有一个函数,它接受一个有两个变量的枚举,并将其转换为一个特定的变量。我只能让它在不安全的ptr::{read,write}
下编译,但感觉应该可以在安全的代码中完成-我无条件地分配给*self
,所以它应该被找到以消耗(部分)当前值。
有没有办法在安全的Rust中编写这个函数?
error[E0507]: cannot move out of `*x` which is behind a mutable reference
--> src/lib.rs:9:29
|
9 | *self = Self::B(*x);
| ^^ move occurs because `*x` has type `T`, which does not implement the `Copy` trait
个字符
Playground的
3条答案
按热度按时间toe950271#
问题是你不能“临时”移动
&mut self
中的T
--如果后面的代码在移动一个值之前发生了恐慌怎么办?这就是为什么在安全的Rust中不可能以你描述的方式移动。解决方案是在self中放入一个值作为临时值,这样
&mut self
就保持在一个定义良好的状态,同时获得所包含的T
的所有权。如果T: Copy
,如果T: Default
,或者如果Foo
有一个独立于T
的廉价变体,这很容易实现。字符串
56lgkhnf2#
如果
Foo::A
和Foo::B
在结构上是相同的,但只需要通过它们的标签来区分,那么标签可能应该完全是一个单独的枚举。字符串
现在不需要移动任何东西了,我们只需要更新标签,然后做其他内部逻辑需要做的事情。
型
yshpjwxd3#
第三种选择是修改
Foo<T>
,以考虑在获取内部值和再次放入内部值之间的中间状态。字符串
请注意,在这样一个小例子中,多一个变量可能会很不方便,因为你必须考虑其他地方的中毒情况。但是,如果你在一个更大的代码库中,很难确保在你获取值的那一刻和你把它放回去的那一刻之间没有任何事情发生。(特别是如果你使用
unsafe
Rust),特别是因为exception safety。如果你强迫每个人都处理出错的情况,突然之间你就不必再确保一切正常了,这是一个不太可能在未来产生bug的设计选择。这种设计在实践中使用,特别是在并发数据结构中,其中推理两个连续指令之间应该发生什么和不应该发生什么特别困难。