[英]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) }
您的兩個指針begin
和end
派生自v1
和v2
,因此它們僅在v1
和v2
存在時才有效,但v1
和v2
相互沖突。
綜上所述,我不能確定允許這個程序是否可行,因為畢竟它不會創建任何實際的可變別名。 我絕對沒有受過 Miri 檢查的 Stacked Borrows model 理論基礎的教育。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.