Rust中无法修改函数签名时如何对不可变slice排序
问题解决方法
首先明确:不存在安全的将不可变共享切片&[i32]直接转换为可变切片&mut [i32]的方案,所有通过unsafe强转指针绕过借用检查的写法都会违反Rust的别名规则,属于未定义行为,会导致无法预期的程序错误,绝对不要使用。
你需要的异地排序可以通过拷贝数据到自有可变容器实现,之前尝试克隆失败基本是写法问题,正确实现如下:
fn foo(xs: &[i32]) { // 将不可变切片的内容拷贝为当前函数持有的可变Vec let mut sorted_xs = xs.to_vec(); // 对自有Vec执行排序,完全符合借用规则 sorted_xs.sort(); // 后续计算逻辑直接使用sorted_xs即可,Vec支持所有切片的操作:索引、迭代、切片切割等 // 如果后续逻辑需要传入&[i32]类型参数,直接传&sorted_xs就会自动转换,无需额外处理 }
常见踩坑说明
- 不要直接对
xs调用clone()后尝试排序:xs本身是&[i32]类型,直接调用clone()得到的还是共享引用&[i32],依然没有修改权限。用to_vec()方法是切片转自有可变Vec的标准写法,不会出现类型匹配问题。 - 不要尝试通过重新绑定可变变量来修改原切片:类似
let mut xs = xs;的写法只是把引用本身绑定为可变变量,没有改变引用指向的共享只读数据的权限,依然无法调用sort()方法。 - 不要使用unsafe绕过借用检查强转可变切片:这类写法违反Rust内存安全规则,属于未定义行为,可能触发段错误、编译器优化逻辑异常等不可排查的问题。
如果你的后续计算逻辑只需要按排序后的顺序迭代元素,不需要随机访问,也可以通过迭代器收集后排序,本质和上面的方案逻辑一致,都是在当前函数持有的内存空间存放可修改的副本,不会影响原切片的数据。
内容的提问来源于stack exchange,提问作者nawat
相关产品推荐
相关产品推荐

