Rust 可以通过获取可变引用来移动值吗?
Rust 可以通过获取可变引用来移动值吗?,rust,Rust,pub-trait-Skip{ fn跳过(&mut self,步骤:usize); } 为我请求跳过{ fn跳过(&mut self,mut步骤:usize){ 为了自己{ 步骤-=1; 如果步骤:20:22 19 |>字符跳过(2); |>----值移到了这里 20 |>println!(“{:?}”,chars.collect::()); |>^^^^^移动后此处使用的值 :20:22:20:27:注意:在格式的扩展中_args! :20:22:20:27:注意:在此打印扩展中!(在中定义)
pub-trait-Skip{
fn跳过(&mut self,步骤:usize);
}
为我请求跳过{
fn跳过(&mut self,mut步骤:usize){
为了自己{
步骤-=1;
如果步骤:20:22
19 |>字符跳过(2);
|>----值移到了这里
20 |>println!(“{:?}”,chars.collect::());
|>^^^^^移动后此处使用的值
:20:22:20:27:注意:在格式的扩展中_args!
:20:22:20:27:注意:在此打印扩展中!(在中定义)
:20:22:20:27:注意:在此println!(在中定义)的扩展中
注意:发生移动是因为'chars'具有'std::str::chars'类型
可以通过获取可变引用来移动值吗
不。引用不会移动引用的项目。这是一个很大的引用点
但是,它确实拥有迭代器的所有权,这是一种移动:
fn skip(self, n: usize) -> Skip<Self>
但是,请注意,不使用迭代器适配器调用迭代器适配器不会产生任何效果:
警告:必须使用未使用的结果:迭代器适配器是惰性的,除非已使用,否则不会执行任何操作
这里真正的问题是,您没有调用您认为是的skip
。如果您将方法重命名为skip2
,您将看到它按预期工作
这是因为方法查找优先选择先按值(self
)再按引用(&self
)再按可变引用(&mut self
)接受接收方的方法
选择与标准库相同的方法名可能是一个坏主意,尤其是对于迭代器,但是非常令人惊讶的是,没有打印一条警告,指出范围内有多个适用的方法
您可以使用指定要调用的实现:
pub trait Skip: Iterator {
fn skip(&mut self, steps: usize) {
for _ in self.take(steps) {}
}
}
impl<I> Skip for I where I: Iterator {}
fn main() {
let s = "abc123def";
let mut chars = s.chars();
Skip::skip(&mut chars, 2);
println!("{:?}", chars.collect::<String>());
}
pub-trait-Skip:迭代器{
fn跳过(多个自身,步骤:usize)(&M){
为{in self.采取(步骤){}
}
}
I的impl Skip,其中I:Iterator{}
fn main(){
设s=“abc123def”;
设mut chars=s.chars();
跳过::跳过(&多个字符,2);
println!(“{:?}”,chars.collect::());
}
如果将Skip::Skip
更改为直接获取I
,或者在mut引用上调用它(例如,(&mut chars)。Skip(2)
)。否则它是合法的原因是,Iterator
的方法不需要autoref,因此它更具体,因此更可取。rustc
中的lint非常简单,但可能clippy对此有一个lint。@delnan我想知道是否有一个选择方法的顺序(self
then&self
then&mut self
)和“多种适用方法”只有在同一个类中有多个方法时才会发生错误?@Shepmaster我认为这是根据是否需要autoref来表述的,但基本上是肯定的。答案解释了为什么这不起作用以及如何解决它,但老实说,很可能最好只使用stdlib的skip
,即使它的API(它是一个迭代器适配器,而不是一个变异的方法)。@delnan经过一些变异迭代器的实验后,我同意!
chars.by_ref().skip(2);
pub trait Skip: Iterator {
fn skip(&mut self, steps: usize) {
for _ in self.take(steps) {}
}
}
impl<I> Skip for I where I: Iterator {}
fn main() {
let s = "abc123def";
let mut chars = s.chars();
Skip::skip(&mut chars, 2);
println!("{:?}", chars.collect::<String>());
}