【问题标题】:Why deref coersion doesn't work for nested Vec?为什么 deref coersion 对嵌套的 Vec 不起作用?
【发布时间】:2021-01-02 23:14:31
【问题描述】:

可以将Vec 传递给函数,期望带有隐式coersion 的切片:

fn foo(arg: &[u8]) {}

foo(&vec![]); // compiles fine

为什么这不能扩展到嵌套切片和 Vecs?

fn bar(arg: &[&[u8]]) {}

bar(&vec![&vec![]]); // Compilation error

// Can be worked around by explicit conversion to slices
bar(&vec![&vec![][..]][..]);

Example in the playground.

【问题讨论】:

    标签: rust


    【解决方案1】:

    因为dereferencing Vec<T> (src) 产生&[T],即给定Vec<Vec<u8>>,它产生&[Vec<u8>] 而不是&[&[u8]]。

    最终,您需要map()、deref()/as_slice() 和collect() 才能获得&[&[u8]]:

    let v: Vec<Vec<u8>> = ...;
    
    let v = v.iter().map(std::ops::Deref::deref).collect::<Vec<_>>();
    // or
    let v = v.iter().map(Vec::as_slice).collect::<Vec<_>>();
    
    bar(&v);
    

    或者,根据上下文,您可以将bar() 更改为通用函数并接受IntoIterator。那么两者都是可能的:

    fn bar<I, T>(iter: I)
    where
        I: IntoIterator<Item = T>,
        T: AsRef<[u8]>,
    {
        ...
    }
    
    bar(&vec![&vec![]]);
    bar(&vec![&vec![][..]][..]);
    

    &amp;vec![&amp;vec![]] 不起作用的原因是,内部&amp; 不会导致Vec&lt;u8&gt; 取消引用到&amp;[u8],而是仅引用Vec 导致&amp;Vec&lt;u8&gt;。

    外部的&amp; 然后不起作用,因为bar 需要&amp;[&amp;[u8]]。但它接收&amp;Vec&lt;&amp;Vec&lt;u8&gt;&gt; 并且取消引用&amp;[&amp;Vec&lt;u8&gt;] 仍然不是bar 所期望的。这就是为什么您会收到mismatched types 错误。

    您的第二个示例 &amp;vec![&amp;vec![][..]][..] 有效,因为您明确导致 Vecs 都被取消引用到切片。 然而,这可以使用as_slice(),即bar(vec![vec![].as_slice()].as_slice());,“简化”成更可读的东西。 但是,最终要从任意 Vec&lt;Vec&lt;u8&gt;&gt; 获得 &amp;[&amp;[u8]],您需要取消引用并收集到新的 Vec&lt;&amp;[u8]&gt;。

    相关:"What are Rust's exact auto-dereferencing rules?"

    【讨论】:

    • 要为此添加上下文,可以说您需要显式的map/collect 是有意义的,因为创建&amp;[&amp;[u8]] 可能会为所有&amp;[u8]s 分配足够的内存并为每个&amp;[u8]s 工作原始 Vec 中的项目。该 Vec 中可能有一百万个&amp;[u8]s;您不想使用空间并隐式地为每个项目工作。
    • 非常感谢这个详尽的回答。它真的帮助我理解了这一点。
    猜你喜欢
    • 1970-01-01
    • 2017-09-06
    • 1970-01-01
    • 1970-01-01
    • 2022-06-10
    • 2018-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多