矢量不会活得足够长,直到我克隆它

时间:2015-12-30 19:28:36

标签: rust borrow-checker

我不明白为什么v在代码段(2)中的生存时间不够长,但在其他情况下却有效。如果我不需要clone (1)中的fn main() { // (1) let v = make_vec().unwrap(); let m = v.last(); // (2) v doesn't live long enough! let m = make_vec() .and_then(|v| v.last()); // (3) Fixed! let m = make_vec() .and_then(|v| v.last().cloned()); } fn make_vec() -> Option<Vec<u32>> { Some(vec![1, 2, 3]) } 变量,为什么我需要克隆它以使第二种情况起作用?

protected void gvwSACLot_Solic_RowCommand(object sender, GridViewCommandEventArgs e)
{
    string server = System.Environment.MachineName.ToString();


    foreach (GridViewRow row in gvwSACLot_Solic.Rows)
    {
        string LotCliCod = Convert.ToString(row.Cells[0].Controls.OfType<Label>().FirstOrDefault().Text);
        string LotCajCod = Convert.ToString(row.Cells[1].Controls.OfType<Label>().FirstOrDefault().Text);
        int LotCajNum = Convert.ToInt16(row.Cells[2].Controls.OfType<Label>().FirstOrDefault().Text);

        if (e.CommandName == "DescargarLot")
        {
            string filename = e.CommandArgument.ToString();
            if (filename != "")
            {

                string filepath = '\\' + server+ '\\' + "IMAGES" +
                LotCliCod + '\\' + LotCajCod + '\\' + LotCajNum + '\\' + filename;

                byte[] bts = System.IO.File.ReadAllBytes(filepath);
                Response.ClearHeaders();
                Response.AddHeader("Content-Disposition", "attachment;   filename=" + filename);
                Response.BinaryWrite(bts);
                Response.Flush();
                Response.End();
            }
        }
    }

1 个答案:

答案 0 :(得分:4)

在第一种情况下,>>> x = [print(i) for i in xrange(10)] 0 1 2 3 4 5 6 7 8 9 >>> x [None, None, None, None, None, None, None, None, None, None] >>> 的所有权从Option传递到make_vec来电。 unwrap 使用选项并返回unwrap,其所有权传递给变量Vec。对v的调用会将引用返回last

在第二种情况下,v的所有权从Option传递到make_vecand_then 使用 and_then,并将Option的所有权传递给关闭。闭包中对Vec的调用会返回last的引用。由于闭包拥有向量但现在已完成运行,因此Vec将被删除。对Vec的引用将指向不再有效的内存,因此编译错误。

在第三种情况下,Vec的所有权从Option传递到make_vecand_then 使用 and_then,并将Option的所有权传递给关闭。闭包中对Vec的调用会返回last的引用。克隆了引用的项目,该项目创建了一个与Vec不同的新项目。在关闭后删除Vec时,没有可能导致问题的引用。

Vec的类型在您的案例中有所不同。如果它们都有效,则第一个和第二个案例将返回m。第三种情况返回Option<&u32>

还有第四种选择:

Option<u32>

这会将let r = make_vec(); let m = r.as_ref().and_then(|v| v.last()); 转换为Option<T>。这个新的Option<&T>引用了原始选项,可以通过调用Option来使用。

还有第五种选择! ^ _ ^如果你只是要扔掉矢量,你可以更明确地说明你想要接受它的事实:

and_then
  

这里的clone实际上是在内存中复制内容还是编译器优化它以有效地传递向量元素的所有权?由于这是u32s,我一直期望它们通常会被复制而不是被引用。

优化是一件棘手的事情,唯一真正的答案是看优化输出。 会认为let m = make_vec().and_then(|v| v.pop()); 并且“足够小”的任何内容都不会导致问题。但是,为了帮助优化器,我可能会考虑尽可能使代码成为语义。如果代码是你的意思,我可能会尝试使用Copy变体。