繁体   English   中英

Rust split_at_mut 的实现

[英]Rust implementation of split_at_mut

我一直在阅读 Rust Book,在关于 Unsafe Rust 的部分中,它展示了如何实现split_at_mut方法的简单版本。 给定的实现是:

use std::slice;

fn split_at_mut(values: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) {
    let len = values.len();
    let ptr = values.as_mut_ptr();

    assert!(mid <= len);

    unsafe {
        (
            slice::from_raw_parts_mut(ptr, mid),
            slice::from_raw_parts_mut(ptr.add(mid), len - mid),
        )
    }
}

但是,我想出了这个:

fn split_at_mut(values: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) {
    let len = values.len();
    assert!(mid <= len);

    let begin = &mut values[..mid] as *mut [i32];
    let end = &mut values[mid..] as *mut [i32];
    
    unsafe {
        (&mut *begin, &mut *end)
    }
}

这会产生(据我所知)相同的结果,但在我看来,它更易于阅读。

那么是什么让给定的解决方案比我的“更好”呢? 我的解决方案是否存在安全(或其他)问题? 给定的解决方案实际上更容易阅读吗? 是关于将此方法扩展到其他切片吗? 是关于编码风格和“良好实践”吗?

期待您的回答

这是我认为的原因(正如另一个答案所写)Miri 拒绝您的代码:

(
    slice::from_raw_parts_mut(ptr, mid),
    slice::from_raw_parts_mut(ptr.add(mid), len - mid),
)

在这种情况下,您正在从来自单个&mut引用values的指针构造两个非重叠的&mut引用。

let begin = &mut values[..mid] as *mut [i32];
let end = &mut values[mid..] as *mut [i32];
    
unsafe {
    (&mut *begin, &mut *end)
}

在这种情况下,您正在构建两个临时可变引用,它们都从values中借用(因此不能同时存在),然后从指针“复活”(不是技术术语)它们。

这是相同代码的一个版本,它扩展了一些临时变量和语法糖:

use std::ops::IndexMut;

let begin = {
    let v1 = &mut values;
    IndexMut::index_mut(v1, ..mid) as *mut [i32]
};
let end = {
    let v2 = &mut values;
    IndexMut::index_mut(v2, mid..) as *mut [i32]
};

unsafe { (&mut *begin, &mut *end) }

您的两个指针beginend派生自v1v2 ,因此它们仅在v1v2存在时才有效,但v1v2相互冲突。

综上所述,我不能确定允许这个程序是否可行,因为毕竟它不会创建任何实际的可变别名。 我绝对没有受过 Miri 检查的 Stacked Borrows model 理论基础的教育。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM