【问题标题】:Rust AsMut copying rather than taking mutable reference?Rust AsMut 复制而不是采用可变引用?
【发布时间】:2022-01-24 09:10:53
【问题描述】:

我对@9​​87654321@ 的理解是,它应该提供一种通用的方式来获取与可变引用“等效*”的参数,即它可以廉价地转换为可变引用。

但是,我遇到了以下示例代码,我试图使用AsMut 只是为了通用slicearrVec,但它似乎只是在复制我的数组,而不是将可变引用传递给它并就地修改它:

    pub fn uses_asmut<T, M>(mut m: M)
    where M: AsMut<[T]> {
        m.as_mut().swap(0,1);
    }
    #[test]
    pub fn test_swap() {
        let arr = [1,2];
        uses_asmut(arr);
        assert_eq!(arr, [2,1]);
    }

(注意,我知道一定有问题,因为我显然将arr 的所有权作为参数传递给uses_asmut,但是当我再次使用arr 时,借用检查器不会在下一行抱怨!如果我将其更改为uses_asmut(&amp;mut arr),则测试通过,但我认为编写的代码甚至不应该编译!)

【问题讨论】:

  • 我认为这仅仅是由于数组实现了Copyuses_asmut(arr); 在按值传递时会复制它。
  • 绑定在uses_asmut() 中的AsMut 允许您使用arr&amp;mut arr 调用它。如果你用arr 调用它,你必须接受数组将被移动(或复制)到函数中。您的let arr = [1, 2] 甚至不包括mut 的事实表明该数组不会改变。如果您在 AsMut 背后的想法是调用 uses_asmut(arr) 并将其脱糖到 uses_asumut(&amp;mut arr),我认为这是不可能的,Rust 不会那样工作。您必须将&amp;mut 设为显式,或将uses_asmut() 实现为宏。
  • 在函数参数上放置一个特征绑定会限制你可以传入的类型。它不会改变这些类型的任何内容,或者它们的行为方式。
  • 谢谢@MartinGallagher 我想这是我的困惑。我希望 arr 被移动,但它被复制了,因为数组实现了Copy

标签: rust slice


【解决方案1】:

转化应该很便宜。但是你是按值传递数组的,而且从来没有说这很便宜。您可以通过 &amp;mut arr 不复制数组。

当我们说转换应该便宜时,我们的意思是“不要做像str::from_utf8_mut() 这样的事情”,它需要扫描整个字符串。事实上,从[T; N][T] 的转换非常便宜:如此便宜,编译器会自动发生(强制)。

但这并不意味着它等同于可变引用,因为它不是可变引用。它是一个泛型类型。如果您想要一个可变引用,请获取一个可变引用。你甚至可以使用AsMut,比如&amp;mut impl AsMut&lt;[T]&gt;

AsMut 无法阻止您移动(或复制)内容,但也不需要您在呼叫站点键入 &amp;mut

【讨论】:

  • 建议将第一段中的“移动”和“不移动”改为“复制”和“不复制”。由于数组是Copy,实际上它没有 被移动(在Rust 意义上)到函数中,这从它在调用者中仍然可用就证明了这一点。另外,请注意 &amp;mut impl AsMut&lt;[T]&gt; 并不是很有用,因为那时 OP 可以只接受 &amp;mut [T]
  • 感谢您的回答,我没有意识到数组实现Copy。我认为&amp;mut impl AsMut&lt;[T]&gt; 是正确的类型,用于接受对类似切片的可变引用。
  • @user4815162342 我不确定是写“复制”还是“移动”,但决定写“移动”,因为它听起来更笼统(本质上,复制是移动而不会使原件无效) .而不是任何实现&amp;mut impl AsMut&lt;[T]&gt; 的类型强制转换为&amp;mut [T]
  • “移动”可能听起来更笼统,但事实并非如此——移动和复制在 Rust 中是相互排斥的。例如,这本书在讨论复制时说复制的数据wasn't moved。您正在寻找的更通用的术语可能是“按值传递”。
  • @user4815162342 公平,已编辑。
猜你喜欢
  • 2018-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多