将Vec <t>转换为&amp; [T]的安全方法是什么?

时间:2016-12-16 02:14:49

标签: rust

如何在不在内存中移动它的情况下为向量的基础堆分配分配生命周期?

我发现这样做的最简单方法是

pub fn heap_slice<'a, T:'a>(x: Vec<T>) -> &'a [T] {
    use std::mem::forget;
    use std::slice::from_raw_parts;
    x.shrink_to_fit();
    let ptr = x.ptr();
    let len = x.len();
    forget(x);
    unsafe{ from_raw_parts(ptr,len) };
}

但这确实在stdlib之外调用unsafe,这通常是不受欢迎的。有安全的方法吗?

我看到into_boxed_slice做的大致完全相同。但是如何恢复&[T]并在Box<[T]>后为其分配生命周期?

1 个答案:

答案 0 :(得分:6)

切片(&'a [T])应该表示某个数组的视图,该数组由另一个对象(例如Vec<T>Box<[T]>)拥有。这就是为什么引用具有生命周期参数而Vec<T>Box<[T]>没有。

当切片被“丢弃”时,没有释放内存,因为切片不拥有内存。因此,您的函数会导致向量的存储泄漏。您不能只是“奇怪地”为切片“生命分配”生命周期并使编译器插入代码以释放堆分配。试想一下,复制切片时会发生什么?

Rust会自动将矢量或盒装切片强制转换为需要切片的上下文中的切片(除非涉及泛型),所以实际上没有理由违反规则并在应该返回时返回切片矢量或盒装切片。

也许你正在编写一个库而你担心返回一个向量会暴露一些实现细节?好吧,这样想吧:如果你用C语言编写库,你会使用原始指针,但是你必须在API文档中写入调用者是否应该调用某个函数(以及哪一个)来清理资源与否。在Rust中,我们使用正确的返回类型对这些指令进行编码,以便程序员不必担心它。

  

你能否至少提供一个如何借用Box<[T]>的代码示例? as_ref()borrow()不允许终身分配

Box<[T]>借用的最短路径是写&x&*x(其中xBox<[T]>)。 &x生成&Box<[T]>类型的值,可以强制转换为&[T],因为Box实现了Deref特征。

为了从函数返回具有有效生命周期参数的切片,必须将其链接到函数输入参数之一的lifetime参数。如果你将Box<[T]>的值传递给函数,那么就没有你可以链接到的生命周期,因为Rust期望在函数结束时删除Box(你可以通过调用mem::forget,但编译器无法推断这一点)。你总是可以通过引用传递Box<[T]>(即&Box<[T]>),但这只会引入一个不必要的间接层,所以你的函数应该只接受&[T]