Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/rust/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Rust 如何转换Vec<;T>;到Vec<;U>;不复制向量?_Rust - Fatal编程技术网

Rust 如何转换Vec<;T>;到Vec<;U>;不复制向量?

Rust 如何转换Vec<;T>;到Vec<;U>;不复制向量?,rust,Rust,我想把Vec转换成Vec,其中T是某种原语,U是T的一种新类型:struct U(T) 我试过这样的方法: struct Foo(u32); fn do_something_using_foo(buffer: &mut Vec<Foo>) {} fn main() { let buffer: Vec<u32> = vec![0; 100]; do_something_using_foo(&mut buffer as Vec<Fo

我想把
Vec
转换成
Vec
,其中
T
是某种原语,
U
T
的一种新类型:
struct U(T)

我试过这样的方法:

struct Foo(u32);

fn do_something_using_foo(buffer: &mut Vec<Foo>) {}

fn main() {
    let buffer: Vec<u32> = vec![0; 100];

    do_something_using_foo(&mut buffer as Vec<Foo>);
}
不能在“安全保护”中更改值的类型。不能保证这两种类型具有相同的大小或相同的语义

这适用于单个值(
T
->
U
)以及聚合值(
Vec
->
Vec
HashMap
)。请注意,聚合值实际上只是“单个”值的特例


最好是创建一个新的向量:

let buffer2 = buffer.into_iter().map(Foo).collect();
您还可以使用_foo调整
do\u something\u,以采用一种通用类型,该类型由
foo
u32
实现:

use std::borrow::{Borrow, BorrowMut};

#[derive(Debug, Clone)]
struct Foo(u32);

impl Borrow<u32> for Foo {
    fn borrow(&self) -> &u32 {
        &self.0
    }
}

impl BorrowMut<u32> for Foo {
    fn borrow_mut(&mut self) -> &mut u32 {
        &mut self.0
    }
}

fn do_something_using_foo<T>(buffer: &mut [T])
where
    T: BorrowMut<u32>,
{
}

fn main() {
    let mut buffer_u32 = vec![0u32; 100];
    let mut buffer_foo = vec![Foo(0); 100];

    do_something_using_foo(&mut buffer_u32);
    do_something_using_foo(&mut buffer_foo);
}
使用std::borrow:{borrow,BorrowMut};
#[派生(调试、克隆)]
结构Foo(u32);
为Foo的impl借钱{
fn借用(和自)->u32{
&self.0
}
}
Foo的impl-breawmut{
fn借用&mut-mut(&mut-self)->&mut-u32{
&mutself.0
}
}
fn使用\u foo(缓冲区:&mut[T])做某事
哪里
T:借用一下,
{
}
fn main(){
让mut buffer_u32=vec![0u32;100];
让mut buffer_foo=vec![foo(0);100];
使用\u-foo(&mut-buffer\u-32)做某事;
使用\u-foo(&mut-buffer\u-foo)做某事;
}

在不安全的锈蚀中,技术上是可能的——你可以随心所欲地射中自己的脚

如果你知道自己在做什么,你可以使用类似的方法

但是,将
transmute
Vec
一起使用是未定义的行为,因为未定义
Vec
的表示形式。相反,请参见

另见:

根据,使用
Vec::from_raw_parts
手动下降
相结合是最佳选择,从Rust 1.38开始:

let v_from_raw = unsafe {
    // Ensure the original vector is not dropped.
    let mut v_clone = std::mem::ManuallyDrop::new(v_orig);
    Vec::from_raw_parts(v_clone.as_mut_ptr() as *mut U,
                        v_clone.len(),
                        v_clone.capacity())
};
这样做的前提是
T
U
具有相同的大小和相同的最小对齐方式,并且对
T
有效的所有位模式也对
U
有效。如果您在问题中定义了
T
U
,您对此没有保证

structu(T)
定义了一个元组结构,而这种结构的内存布局是完全未定义的。但是,可以使用以下方法强制内存表示相同:

未来的可能性 夜间生锈,减少了代码数量和出错位置:

#![feature(vec_into_raw_parts)]

fn convert_using_into_raw_parts(v: Vec<T>) -> Vec<U> {
    let (ptr, len, cap) = v.into_raw_parts();
    unsafe { Vec::from_raw_parts(ptr as *mut U, len, cap) }
}
#![特征(将向量转化为原始零件)]
fn使用_将_转换为_原始_零件(v:Vec)->Vec{
让(ptr,len,cap)=v.进入原始零件();
不安全{Vec::来自原始零件(ptr as*mut U,len,cap)}
}

还有一个开放式RFC建议添加一个
Vec::transmute
方法。

只是为了澄清:您需要以
和[U]
和mut[U]
和mut-Vec
的形式访问
Vec
?(提示:切片的选择要简单得多。)@BLUS对于我的情况
&mut[U]
是可以接受的,尽管
&mut-Vec
更可取。如果
&mut[U]
是可以接受的,那么。很久以前
Vec
有一个
fn-map\U(self,f:f)->Vec
方法,当
T
U
的大小相同时,这将起作用。它在锈1.4中被移除,但似乎有一个板条箱可以做到这一点。在这种情况下,可能是杀伤力过大。无法保证这两种类型的大小相同。至少,这是可以验证的:
std::mem::size\u of
。对于无操作就地转换,您不需要像旧的
map\u in\u place()一样复杂的东西。其复杂性的原因主要是,当向量的部分已经具有类型
U
,而其余部分仍然是类型
T
时,它必须处理中间状态。即使在出现恐慌的情况下也要做到这一点是相当困难的。但是,如果源类型和目标类型具有相同的内存布局,并且您只想将内存重新解释为不同的类型,那么这可以相对容易地完成。文档说,
transmute
相当于C的memcpy,因此我认为这不符合“不复制向量”的标准。我之所以提到这一点,是因为这是谷歌对“rust transmute而不复制”的一个高级搜索结果。@detly是的,
Vec
的24字节(在64位机器上)被复制。数据不会被复制。否则,您需要转换
&Vec
的8个字节,这仍然需要复制这8个字节。@detly是的,这是正确的。
#![feature(vec_into_raw_parts)]

fn convert_using_into_raw_parts(v: Vec<T>) -> Vec<U> {
    let (ptr, len, cap) = v.into_raw_parts();
    unsafe { Vec::from_raw_parts(ptr as *mut U, len, cap) }
}