对象移动和借用解释 int rev()、chars() 和 next()
Explanation of objects moves and borrowings int rev(), chars() and next()
嗨,所有。为了理解移动和借用操作的规则,我编写了以下代码:
let company:&str="TutorialsPoint";
let test_chars = company.chars(); // move
let test_chars_1 = company.chars(); // move
let test_chars_rev = &test_chars_1.rev(); // move --explicit type here is &std::iter::Rev<std::str::Chars<'_>>
let test_chars_rev_next = test_chars_1.rev().next(); //move --creates an error that the line before a move occurred
let test_chars_rev_next_copy = test_chars_rev_next;
println!("Char indices test reverse: {:?}", test_chars_rev);
println!("Char indices test reverse: {:?}", test_chars_rev_next);
现在按照我的逻辑。下面一行应该是借而不是移动。
let test_chars_rev = &test_chars_1.rev(); // move
但这会造成一种奇怪的情况。我希望 & 运算符创建一个借用操作,移动基本上是 Self -> Self 移动。但事实并非如此。如果移动仍然发生,& 会向新移动的对象传递新的引用,还是对象仍然是相同的,只是这个所有权概念开始起作用(所有权从 test_chars_1 转移到 test_chars_rev)?
在这种情况下,我该如何设想所有权,例如移动引用,或者在跟踪事物的编译器中是否有魔术?
当然我尝试了下面的场景。
let test_chars = company.chars(); // move
let test_chars_1 = company.chars(); // move
let test_chars_rev = test_chars.rev(); // move
let test_chars_rev_next = test_chars_1.rev().next(); //move
let test_chars_rev_next_copy = test_chars_rev_next;
println!("Char indices test reverse: {:?}", test_chars_rev);
println!("Char indices test reverse: {:?}", test_chars_rev_next);
这里一切正常。但是结果有点尴尬
Char indices test reverse: Rev { iter: Chars(['T', 'u', 't', 'o', 'r', 'i', 'a', 'l', 's', 'P', 'o', 'i', 'n', 't']) }
Char indices test reverse: Some('t')
第二行尤其令人难以置信。我做了一个 next() 操作,突然我没有要写的字符,但只有 1 个字符。为什么?我看了一下next()函数的实现好像很正常
在试图弄清楚一个方法是执行移动还是借用时,要注意的一件重要事情是查看它的签名。
&str
上的方法 chars
具有 following signature:
pub fn chars(&self) -> Chars<'_>
正如您在 self
中使用的 &
所见,此方法 借用 它调用的值,以 return名为 Chars
的结构实现了 Iterator
特征(next
方法的来源)。
如果你查看 rev
的 signature,它来自 Iterator
特征,你会看到它 移动 值它被称为:
fn rev(self) -> Rev<Self>
还有一点需要注意的是,在变量前放一个&
会提取对它的引用,它不会使操作借用而不是移动。操作移动或借用行为被烘焙到它的签名中。
所以发生的事情如下:
let company: &str = "TutorialsPoint";
let test_chars = company.chars(); // borrow
let test_chars_1 = company.chars(); // borrow
let test_chars_rev = &test_chars_1.rev(); // move and then `&` extracts a reference
let test_chars_rev_next = test_chars_1.rev().next(); // tries to use a moved value, error (value moved to `test_chars_rev`)
let test_chars_rev_next_copy = test_chars_rev_next;
println!("Char indices test reverse: {:?}", test_chars_rev);
println!("Char indices test reverse: {:?}", test_chars_rev_next);
您可以检查对 chars
的调用是否是借用,因为您在 company
上调用了该方法,但之后您仍然使用了 company
。
最后是next
方法(在Iterator中定义)returns Option<Self::Item>
,而不是迭代器本身。这就是为什么当你修复所有权错误时,你会发现自己在第一次打印时有一个迭代器,而在第二次打印时只有一个 Option
值。
let test_chars = company.chars(); // move
借用 company
,创建一个迭代器并将此迭代器移动到 test_chars
.
let test_chars_rev = test_chars.rev(); // move
将 test_chars
移动到 rev
,其中 returns 一个新的迭代器被移动到 test_chars_rev
.
let test_chars_rev_next = test_chars_1.rev().next(); //move
将 test_chars_1
移动到 rev
,其中 returns 一个新的迭代器被移动到一个临时的,然后 next
借用那个临时的 returns 它的第一个移入 test_chars_rev_next
的值。然后丢弃临时文件。
let test_chars_rev_next_copy = test_chars_rev_next;
将 test_chars_rev_next
复制到 test_chars_rev_next_copy
。这是一个副本,而不是移动,因为 test_chars_rev_next
的类型 Option<&char>
实现了 Copy
.
嗨,所有。为了理解移动和借用操作的规则,我编写了以下代码:
let company:&str="TutorialsPoint";
let test_chars = company.chars(); // move
let test_chars_1 = company.chars(); // move
let test_chars_rev = &test_chars_1.rev(); // move --explicit type here is &std::iter::Rev<std::str::Chars<'_>>
let test_chars_rev_next = test_chars_1.rev().next(); //move --creates an error that the line before a move occurred
let test_chars_rev_next_copy = test_chars_rev_next;
println!("Char indices test reverse: {:?}", test_chars_rev);
println!("Char indices test reverse: {:?}", test_chars_rev_next);
现在按照我的逻辑。下面一行应该是借而不是移动。
let test_chars_rev = &test_chars_1.rev(); // move
但这会造成一种奇怪的情况。我希望 & 运算符创建一个借用操作,移动基本上是 Self -> Self 移动。但事实并非如此。如果移动仍然发生,& 会向新移动的对象传递新的引用,还是对象仍然是相同的,只是这个所有权概念开始起作用(所有权从 test_chars_1 转移到 test_chars_rev)?
在这种情况下,我该如何设想所有权,例如移动引用,或者在跟踪事物的编译器中是否有魔术?
当然我尝试了下面的场景。
let test_chars = company.chars(); // move
let test_chars_1 = company.chars(); // move
let test_chars_rev = test_chars.rev(); // move
let test_chars_rev_next = test_chars_1.rev().next(); //move
let test_chars_rev_next_copy = test_chars_rev_next;
println!("Char indices test reverse: {:?}", test_chars_rev);
println!("Char indices test reverse: {:?}", test_chars_rev_next);
这里一切正常。但是结果有点尴尬
Char indices test reverse: Rev { iter: Chars(['T', 'u', 't', 'o', 'r', 'i', 'a', 'l', 's', 'P', 'o', 'i', 'n', 't']) }
Char indices test reverse: Some('t')
第二行尤其令人难以置信。我做了一个 next() 操作,突然我没有要写的字符,但只有 1 个字符。为什么?我看了一下next()函数的实现好像很正常
在试图弄清楚一个方法是执行移动还是借用时,要注意的一件重要事情是查看它的签名。
&str
上的方法 chars
具有 following signature:
pub fn chars(&self) -> Chars<'_>
正如您在 self
中使用的 &
所见,此方法 借用 它调用的值,以 return名为 Chars
的结构实现了 Iterator
特征(next
方法的来源)。
如果你查看 rev
的 signature,它来自 Iterator
特征,你会看到它 移动 值它被称为:
fn rev(self) -> Rev<Self>
还有一点需要注意的是,在变量前放一个&
会提取对它的引用,它不会使操作借用而不是移动。操作移动或借用行为被烘焙到它的签名中。
所以发生的事情如下:
let company: &str = "TutorialsPoint";
let test_chars = company.chars(); // borrow
let test_chars_1 = company.chars(); // borrow
let test_chars_rev = &test_chars_1.rev(); // move and then `&` extracts a reference
let test_chars_rev_next = test_chars_1.rev().next(); // tries to use a moved value, error (value moved to `test_chars_rev`)
let test_chars_rev_next_copy = test_chars_rev_next;
println!("Char indices test reverse: {:?}", test_chars_rev);
println!("Char indices test reverse: {:?}", test_chars_rev_next);
您可以检查对 chars
的调用是否是借用,因为您在 company
上调用了该方法,但之后您仍然使用了 company
。
最后是next
方法(在Iterator中定义)returns Option<Self::Item>
,而不是迭代器本身。这就是为什么当你修复所有权错误时,你会发现自己在第一次打印时有一个迭代器,而在第二次打印时只有一个 Option
值。
let test_chars = company.chars(); // move
借用 company
,创建一个迭代器并将此迭代器移动到 test_chars
.
let test_chars_rev = test_chars.rev(); // move
将 test_chars
移动到 rev
,其中 returns 一个新的迭代器被移动到 test_chars_rev
.
let test_chars_rev_next = test_chars_1.rev().next(); //move
将 test_chars_1
移动到 rev
,其中 returns 一个新的迭代器被移动到一个临时的,然后 next
借用那个临时的 returns 它的第一个移入 test_chars_rev_next
的值。然后丢弃临时文件。
let test_chars_rev_next_copy = test_chars_rev_next;
将 test_chars_rev_next
复制到 test_chars_rev_next_copy
。这是一个副本,而不是移动,因为 test_chars_rev_next
的类型 Option<&char>
实现了 Copy
.