除了这两种,有没有更好的方法可以在铁 rust 中铸造Vec<i8>Vec<u8>

  1. 通过映射和强制转换每个条目来创建副本
  2. 使用std::transmute

(1)是缓慢的,(2)是"蜕变应该是绝对的最后手段"根据docs.

可能需要一点背景知识:我从不安全的gl::GetShaderInfoLog()调用中得到了Vec<i8>,我想用String::from_utf8()从这个字符向量中创建一个字符串.

推荐答案

其他答案为从Vec<i8>创建字符串这一根本问题提供了极好的解决方案.为了回答提出的问题,从Vec<i8>中的数据创建Vec<u8>可以不用复制或转换向量.正如@trentcl所指出的,直接转换向量构成了未定义的行为,因为Vec允许对不同类型有不同的布局.

在不复制矢量数据的情况下传输矢量数据的正确方法(尽管仍然需要使用unsafe)是:

  • 获取向量中数据的*mut i8指针及其长度和容量
  • 泄漏原始向量以防止其释放数据
  • 使用Vec::from_raw_parts构建一个新的向量,将指针强制转换为*mut u8——这是不安全的部分,因为我们正在证明指针包含有效的初始化数据,并且其他对象没有使用它,等等.

这不是UB,因为新Vec从一开始就被赋予了正确类型的指针.代码(playground):

fn vec_i8_into_u8(v: Vec<i8>) -> Vec<u8> {
    // ideally we'd use Vec::into_raw_parts, but it's unstable,
    // so we have to do it manually:

    // first, make sure v's destructor doesn't free the data
    // it thinks it owns when it goes out of scope
    let mut v = std::mem::ManuallyDrop::new(v);

    // then, pick apart the existing Vec
    let p = v.as_mut_ptr();
    let len = v.len();
    let cap = v.capacity();
    
    // finally, adopt the data into a new Vec
    unsafe { Vec::from_raw_parts(p as *mut u8, len, cap) }
}

fn main() {
    let v = vec![-1i8, 2, 3];
    assert!(vec_i8_into_u8(v) == vec![255u8, 2, 3]);
}

Rust相关问答推荐

为什么拥有的trait对象的相等运算符移动了正确的操作数?

go 掉包装 struct 中的泛型

无法在线程之间安全地发送future (&Q;)&错误

使用 struct 外部的属性来改变 struct 的原始方式

获取字符串切片(&;str)上的切片([ia..ib])返回字符串

为潜在的下游实现使用泛型绑定而不是没有泛型绑定的trait

同时从不同线程调用DLL的不同函数会出现分段错误或产生STATUS_STACK_BUFFER_OVERRUN

如何导入crate-type=[";cdylib;]库?

将一个泛型类型转换为另一个泛型类型

在Rust内联程序集中使用字符串常量

可以在旋转循环中调用try_recv()吗?

try 从标准输入获取用户名和密码并删除 \r\n

unwrap 选项类型出现错误:无法移出共享引用后面的*foo

Rust中是否可以在不复制的情况下从另一个不可变向量创建不可变向量?

‘&T as *const T as *mut T’ 在 ‘static mut’ 项目中合适吗?

在 Rust 中实现资源消耗的安全包装器

类型判断模式匹配panic

将数据序列化为 struct 模型,其中两个字段的数据是根据 struct 中的其他字段计算的

您不能borrow 对只读值的可变引用

来自外部函数的future 内部可变引用