Rust 如何修改作为函数参数的切片?
可以将参数传递给函数并进行修改:Rust 如何修改作为函数参数的切片?,rust,Rust,可以将参数传递给函数并进行修改: fn set_42(int: &mut i32) { *int += 42; } fn main() { let mut int = 0; set_42(&mut int); println!("{:?}", int); } : 更改代码以使用切片失败,并出现一系列错误: fn pop_front(slice: &mut [i32]) { *slice = &{sl
fn set_42(int: &mut i32) {
*int += 42;
}
fn main() {
let mut int = 0;
set_42(&mut int);
println!("{:?}", int);
}
:
更改代码以使用切片失败,并出现一系列错误:
fn pop_front(slice: &mut [i32]) {
*slice = &{slice}[1..];
}
fn main() {
let mut slice = &[0, 1, 2, 3][..];
pop_front(&mut slice);
println!("{:?}", slice);
}
:
错误[E0308]:类型不匹配
-->src/main.rs:2:14
|
2 |*slice=&{slice}[1..];
| ^^^^^^^^^^^^^^^
| |
|应为片“[i32]”,找到“&[i32]`
帮助:考虑移除借词:{S{} 1…
错误[E0277]:编译时无法知道类型为“[i32]”的值的大小
-->src/main.rs:2:5
|
2 |*slice=&{slice}[1..];
|^^^^^在编译时没有已知的大小
|
=help:trait`std::marker::Sized`未为“[i32]实现`
=注意:要了解更多信息,请访问
=注意:赋值的左侧必须具有静态已知的大小
如果我们尝试使用可变切片(这不是我真正想要的;我不想修改切片中的值,我只想修改切片本身,使其覆盖更小的元素范围)和可变参数,它对原始切片没有影响:
fn pop_front(mut slice: &mut [i32]) {
slice = &mut {slice}[1..];
}
fn main() {
let mut slice = &mut [0, 1, 2, 3][..];
pop_front(&mut slice);
println!("{:?}", slice);
}
:
有没有办法修改作为函数参数的切片?我不想修改切片中的元素;我只想修改切片本身的范围,使其成为更小的“子切片”。如果需要修改不可变切片 您不能在安全窗口中修改可变切片。当您获取可变切片的子切片时,实际上是从原始切片借用。这意味着子切片的寿命不能超过原始切片 您想要的东西如下所示:
fn pop_front(slice: &mut &mut [i32]) {
*slice = &mut slice[1..];
}
但是子片slice[1..]
仅在函数结束前有效,借阅将在哪一点结束,原始片(slice
参数)将再次可用
我们可以使用一些不安全的代码手动构建我们想要的切片:
use std::slice;
fn pop_front(slice: &mut &mut [i32]) {
let ptr = slice.as_mut_ptr();
let len = slice.len();
*slice = unsafe { slice::from_raw_parts_mut(ptr.offset(1), len - 1) };
}
fn main() {
let mut slice = &mut [0, 1, 2, 3][..];
pop_front(&mut slice);
println!("{:?}", slice);
}
该程序输出:
[1, 2, 3]
如果需要修改不可变切片
您不能在安全窗口中修改可变切片。当您获取可变切片的子切片时,实际上是从原始切片借用。这意味着子切片的寿命不能超过原始切片
您想要的东西如下所示:
fn pop_front(slice: &mut &mut [i32]) {
*slice = &mut slice[1..];
}
但是子片slice[1..]
仅在函数结束前有效,借阅将在哪一点结束,原始片(slice
参数)将再次可用
我们可以使用一些不安全的代码手动构建我们想要的切片:
use std::slice;
fn pop_front(slice: &mut &mut [i32]) {
let ptr = slice.as_mut_ptr();
let len = slice.len();
*slice = unsafe { slice::from_raw_parts_mut(ptr.offset(1), len - 1) };
}
fn main() {
let mut slice = &mut [0, 1, 2, 3][..];
pop_front(&mut slice);
println!("{:?}", slice);
}
该程序输出:
[1, 2, 3]
使用部分(我没有想到尝试&mut&
),我能够在不使用不安全的代码的情况下让它工作:
fn pop_front(mut slice: &mut &[i32]) {
*slice = &slice[1..];
}
fn main() {
let mut slice = &[0, 1, 2, 3][..];
pop_front(&mut slice);
println!("{:?}", slice);
}
:
使用部分(我没有想到尝试&mut&
),我能够在不使用不安全的代码的情况下让它工作:
fn pop_front(mut slice: &mut &[i32]) {
*slice = &slice[1..];
}
fn main() {
let mut slice = &[0, 1, 2, 3][..];
pop_front(&mut slice);
println!("{:?}", slice);
}
:
正如其他人所说,这里的核心思想是采用&mut&。。。[T]
(其中,…
为mut
或空)并读取/写入内部片。其他答案表明,安全代码中可能存在&mut&[T]
,不安全代码中可能存在&mut&mut[T]
,但它们没有解释为什么会有差异。。。而&mut&mut[T]
也可以使用安全代码
在显式生存期术语中,嵌套引用类似于&'a mut&'b。。。[T]
对于一些生命周期'a
和b
,这里的目标是获得&'b。。。[T]
,将其切片并将其写入和'a mut
对于&'a mut&'b[T]
,这很容易:&[T]
是复制的,因此编写*slice=&slice[1..]
将有效地将&'b[T]
从&mut
中复制出来,然后用较短的值覆盖现有值。复制意味着一个人可以用一个&'b[T]
进行操作,因此它与&'a mut
之间没有直接联系,因此变异是合法的。这实际上是类似于
fn pop_front<'a, 'b>(slice: &'a mut &'b[i32]) {
// *slice = &slice[1..] behaves like
let value: &'b [i32] = *slice;
*slice = &value[1..]
}
对于&'a mut&'b mut[T]
而言,安全地执行此操作的方法是从引用中取出具有该'b
生存期的内部片。这需要跟踪“一个所有者”规则,不借钱,而这种所有权操纵的最佳功能是。它允许我们通过交换一些占位符来提取内部的&'b mut[T]
,然后我们可以用短版本覆盖它。最好的/唯一的占位符是空数组:对于任何类型的X
和任何生存期的'c
,写入&mut[]
都可以是&c mut[X]
,因为没有要存储的数据,所以不需要初始化,也没有数据会变得无效。特别是,它可以是a和b mut[T]
:
fn pop_front<'a, 'b>(slice: &'a mut &'b mut [i32]) {
let value: &'b mut [i32] = mem::replace(slice, &mut []);
*slice = &mut value[1..]
}
(如上所述,我把事情说得比必要的更清楚。)
另见:
正如其他人所说,这里的核心思想是采用&mut&。。。[T]
(其中,…
为mut
或空)并读取/写入内部片。其他答案表明,安全代码中可能存在&mut&[T]
,不安全代码中可能存在&mut&mut[T]
,但它们没有解释为什么会有差异。。。而&mut&mut[T]
也可以使用安全代码
在显式生存期术语中,嵌套引用类似于&'a mut&'b。。。[T]
对于一些生命周期'a
和b
,这里的目标是获得&'b。。。[T]
,将其切片并将其写入和'a mut
对于&'a mut&'b[T]
,这很容易:&[T]
是复制的,因此编写*slice=&slice[1..]
将有效地将&'b[T]
从&mu中复制出来
fn pop_front<'a, 'b>(slice: &'a mut &'b mut [i32]) {
let value: &'b mut [i32] = mem::take(slice);
*slice = &mut value[1..]
}