Vec中的Rust元组:使用val0方法时出现编译错误

时间:2014-10-14 16:11:36

标签: rust

在以下情况下出现令人困惑的编译错误:

  • 我创建了一个包含元组的向量,这些元组本身包含字符串
  • 在此向量的任何项目上调用方法“val0”(或“val1”等)

这是一个代码示例:

fn main()
{
    let mut v = Vec::<(int,String)>::new();
    v.push((3, String::new()));

    let u = v[0].val0();
}

产生以下错误:

error: cannot move out of dereference (dereference is implicit, due to indexing)

我认为我对所有权,借用,参考和生命周期有一个合理的理解,但我仍然没有得到这个错误。为什么会这样?

更新

感谢Vladimir和Levans的回答。

弗拉基米尔,我会按照建议使用元组索引语法,但我最感兴趣的是“为什么”。为什么不能这么简单的工作?

正如Levans所说,val0的定义是:

fn val0(self) -> A

我设法进一步简化了我的例子:

fn main()
{
    let t : (int, String) = (3, String::new());
    let u = t.val0();
    let v = t.val1();
}

这给我带来了以下错误:

main.rs:8:13: 8:14 error: use of moved value: `t`
main.rs:8     let v = t.val1();

main.rs:7:13: 7:14 note: `t` moved here because it has type `(int,collections::string::String)`, which is non-copyable (perhaps you meant to use clone()?)
main.rs:7     let u = t.val0();

这就是我要找的东西。我缺少的是复杂类型无法按值复制。因此,它们被移动到被调用的函数的范围。

请注意,以下内容确实有效,因为(int,int)不是复杂类型:

fn main()
{
    let t : (int, int) = (3, 4);
    let u = t.val0();
    let v = t.val1();
}

我仍然认为在原始示例(使用Vec)的错误消息中包含更多信息会非常有用。

2 个答案:

答案 0 :(得分:4)

使用最近的Rust编译器,您不需要valX() / refX()方法,您可以使用元组索引语法。我真的很惊讶他们没有被弃用(可能是因为元组索引仍然在功能门之后)。元组索引如下所示:

#![feature(tuple_indexing)]

fn main() {
    let mut v = Vec::<(int,String)>::new();
    v.push((3, String::new()));

    let u = v[0].0;  // use 1st (with zero-based indices) field of a tuple
    println!("{}", u);
}

幸运的是,这个程序可以正常工作,因为访问元组字段就像访问常规结构中的字段一样 - 它不需要取得整个结构的所有权,它支持部分移动。在这种特殊情况下,第一个字段类型是可隐式复制的,因此您只需访问它就可以复制它。

答案 1 :(得分:3)

val0()的原型是:

fn val0(self) -> A

如你所见,它消耗元组来解开第一个值。因此,当你在v[0]上调用它时,它会有效地尝试将元组移动到val0()的范围内,这是禁止的,因为元组由你的Vec拥有。

您可能想要使用ref0,它会为您提供对第一项的引用,而不会消耗元组:

fn ref0(&'a self) -> &'a A