Vec <pathbuf>到&amp; [&amp; Path]没有分配?

时间:2017-03-11 13:32:12

标签: reference rust slice

我有返回Vec<PathBuf>的函数和接受&[&Path]的函数,基本上是这样的:

use std::path::{Path, PathBuf};

fn f(paths: &[&Path]) {
}

fn main() {
    let a: Vec<PathBuf> = vec![PathBuf::from("/tmp/a.txt"), PathBuf::from("/tmp/b.txt")];

    f(&a[..]);
}

是否可以在没有内存分配的情况下将Vec<PathBuf>转换为&[&Path]

如果没有,我应该如何更改f签名以接受包含PathPathBuf的切片?

3 个答案:

答案 0 :(得分:5)

  

是否可以在没有内存分配的情况下将Vec<PathBuf>转换为&[&Path]

不,正如How do I write a function that takes both owned and non-owned string collections?所回答的那样; PathBufPath有不同的内存布局(答案使用Stringstr;概念是相同的。)

  

如何更改f签名以接受PathPathBuf的切片?

再次按照How do I write a function that takes both owned and non-owned string collections?的建议,使用AsRef

use std::path::{Path, PathBuf};

fn f<P>(paths: &[P])
    where P: AsRef<Path>
{}

fn main() {
    let a = vec![PathBuf::from("/tmp/a.txt")];
    let b = vec![Path::new("/tmp/b.txt")];

    f(&a);
    f(&b);
}

这不需要额外的堆分配。

答案 1 :(得分:0)

要传递切片,您还必须将原始数据保存在某处。要拥有&[&Path],那么这需要指向类似Vec<&Path>的内容。但是你没有其中一个,你有一个Vec<PathBuf>

要使用现有签名,您可以制作一个临时的Vec<&Path>,然后分一杯。

fn f(paths: &[&Path]) {
}

fn main() {
    let a: Vec<PathBuf> = vec![PathBuf::from("/tmp/a.txt"), PathBuf::from("/tmp/b.txt")];
    let paths: Vec<&Path> = a.iter().map(PathBuf::as_path).collect();
    f(&paths[..]);

}

即使这会创建一个新的Vec,这只是堆栈上的几个指针 - 它不必实际复制任何路径。

答案 2 :(得分:0)

在没有任何分配的情况下进行投射是不可能的,因为它们在内存中的布局是不同的。

Vec<PathBuf>以内联方式存储数据,[&Path]存储指向数据的指针(与Vec<&PathBuf>大致相似)。

您需要创建一个新的向量来保存指针。如果在编译时已知大小,则可以使用堆栈分配的数组。否则,需要map + collect