我的目标是将元素移出拥有的Vec
。
fn f<F>(x: Vec<F>) -> F {
match x.as_slice() {
&[a, b] => a,
_ => panic!(),
}
}
如果F
是copy,那就没有问题,因为你可以简单地从slice中复制出来。如果F
不是,slice模式似乎是不可行的,因为slice是只读的。
有没有一个“拥有的切片”,或者Vec
上的模式匹配,可以将元素移出x
?
**编辑:**我现在看到这段代码有更普遍的问题。函数
fn f<T>(x: Vec<T>) -> T {
x[0]
}
留下“a hole in a Vec
“,即使它在之后被丢弃。这是不允许的。这篇文章和this discussion描述了这个问题。
这就引出了更新的问题:如何正确使用Vec<T>
来进行模式匹配?
4条答案
按热度按时间hmtdttj41#
如果你坚持模式匹配,你可以这样做:
然而,如果你只是想检索一个2元素向量的第一个元素(在其他情况下会很恐慌),我想我宁愿这样做:
hivapdat2#
在这种情况下,不能对切片模式使用模式匹配。
正如您在问题编辑中正确提到的,将值移出
Vec
会使其保留未初始化的内存。这可能会在随后删除Vec
时导致Undefined Behaviour,因为其Drop
实现需要释放堆内存,并可能删除每个元素。目前没有办法表示类型参数
F
没有Drop
实现,或者从未初始化的内存中强制它是安全的。你几乎必须忘记使用切片模式的想法,并更明确地编写它:
如果你在模式匹配上已经死定了,你可以使用
Itertools::tuples()
来匹配元组:ncecgwcz3#
实现消费向量的单个元素的一种方法是将最后一个元素与要消费的元素交换,然后弹出最后一个元素
代码使用了一个
unwrap
,这并不优雅。eni9jsuy4#
我在最近的reddit post中遇到了一个很好的模式,它适用于您希望向量具有与您匹配的长度完全相同的情况。
利用
Vec
通过TryFrom
实现TryInto<[T; N]>
的想法(自Rust版本1.48起)。这可以与let else
syntax结合起来对try结果进行模式匹配:如果vector可以有更多的元素,并且无论如何都要丢弃(drop)它们,那么可以预先
truncate
它。