有没有办法强制Rust让我使用可能移动的值?

时间:2018-01-07 21:26:33

标签: rust

我是否忘记了借用和移动是如何工作的?

let mut v = vec![1, 2, 3]; // I have some uncopyable value

if false {
    let t = v; // I might do something that consumes it
}

println!("{:?}", v); // in some condition, I know for sure that I didn't consume it

我可以以某种方式使用unsafe子句告诉编译器相信我吗?

任何解决方案都必须没有运行时开销。

3 个答案:

答案 0 :(得分:10)

即使在不安全的代码中,编译器也不会让您访问可能已移出值的变量。

一些解决方法:

  • 将其包裹在pd.read_csv("train.csv") 中。然后,您可以使用Option方法移出数据,留下take值。

    这是我推荐用于局部变量的方法。

  • 用空向量替换原始向量。这很便宜,因为空载体不会分配。

    None

    这是与C ++移动最接近的等价物,其描述为:

      

    除非另有说明,否则此类移动对象应为   处于有效但未指定的状态。

  • 将其包裹在let t = std::mem::replace(&mut v, Vec::new()); 中(这比ManuallyDrop更安全,因为在发生恐慌时它不会丢弃该值)。将其手动放在它仍然初始化的路径的末尾。使用deref在仍然有效时访问它。 mem::forget复制该值,将原始位置视为无效/未初始化。

    这不应该有任何运行时开销,但我强烈建议不要在局部变量上使用它。它不值得复杂和风险。

    ptr::read

    playground

答案 1 :(得分:4)

没有

  

我确信我没有消耗它

仅仅因为你没有编写任何不使用它的代码并不意味着它没有被消耗掉。 Ownership and conditionally executed code进一步讨论了基于类型和基于堆栈的 drop flags 的机制,但从概念上讲,您的代码是:

let v = vec![1, 2, 3];

if false {
    let _t = v;
    drop(_t);
} else {
    drop(v);
}

println!("{:?}", v);

一旦条件结束,你的价值就越好。 (实现方面,drops do happen at the end of the function,但语义不表达)。

  

在某种情况下

该条件将是else声明的if块:

if false {
    let _t = v;
} else {
    println!("{:?}", v);
}

答案 2 :(得分:2)

如果你想模仿C ++移动语义,只需使用mem::replace

use std::mem;

let mut v = vec![1, 2, 3]; // I have some uncopyable value

if false {
    let t = mem::replace(&mut v, vec![]); // I might do something that consumes it
}

println!("{:?}", v);

vec![]保证不分配内存,因此没有运行时开销。在一般情况下,你需要一些"零"你的不可用类型的值就像在C ++中一样。如果你不能提出"零"值,您可以随时使用Option作为CodesInChaos答案建议。