Rust:使用部分移动的值

edw*_*rdw 3 rust

在Rust 0.8中:

struct TwoStr {
  one: ~str,
  two: ~str,
}

#[test]
fn test_contents() {
  let strs = TwoStr {
    one: ~"pillar",
    two: ~"post",
  };

  assert_eq!(strs.one, ~"pillar");
  assert_eq!(strs.two, ~"post");
}
Run Code Online (Sandbox Code Playgroud)

代码甚至不会编译.在rust test认为有一个在第二的错误assert_eq:

错误:使用部分移动的值: strs

这有点违反直觉.我的意思是,无论第一个assert_eq有什么影响,当执行到达第二个时,它应该远远超出范围assert_eq.除非当然,它会在场景后面产生一些东西.可以?

如果没有,为什么这个神秘的错误呢?希望我对Rust指针的理解没有根本的缺陷.

Lil*_*ard 6

在Rust 0.8中,assert_eq!定义为

macro_rules! assert_eq (
    ($given:expr , $expected:expr) => (
        {
            let given_val = $given;
            let expected_val = $expected;
            // check both directions of equality....
            if !((given_val == expected_val) && (expected_val == given_val)) {
                fail!(\"assertion failed: `(left == right) && (right == \
                left)` (left: `%?`, right: `%?`)\", given_val, expected_val);
            }
        }
    )
)
Run Code Online (Sandbox Code Playgroud)

请注意,它将两个参数都移动到本地let-bindings given_valexpected_val.这是导致您的错误的原因.

在当前的主人,这已得到修复.assert_eq!现在引用参数:

macro_rules! assert_eq (
    ($given:expr , $expected:expr) => (
        {
            let given_val = &($given);
            let expected_val = &($expected);
            // check both directions of equality....
            if !((*given_val == *expected_val) &&
                 (*expected_val == *given_val)) {
                fail!("assertion failed: `(left == right) && (right == left)` \
                       (left: `{:?}`, right: `{:?}`)", *given_val, *expected_val)
            }
        }
    )
)
Run Code Online (Sandbox Code Playgroud)

这意味着它不再移动其参数,从而修复了您的错误.

如果你需要坚持生锈0.8,你可以改为使用assert!()而直接进行比较,这将避免移动.但我的建议是升级到最新的主人.