我想我非常了解,Rust中的&
和*
之间的区别与内存管理有关。
以下代码段之间有什么区别?采用一种方法与另一种方法是否有危险?
for (i, item) in bytes.iter().enumerate() {
if *item == b' ' {
return i;
}
}
for (i, &item) in bytes.iter().enumerate() {
if item == b' ' {
return i;
}
}
for (i, item) in bytes.iter().enumerate() {
if item == &b' ' {
return i;
}
}
据我了解,当我从iter()
返回值时,我返回的是对bytes
中找到的元素的引用。如果要在项目上进行比较,则需要在两个引用&u8
之间进行比较,或者需要将&item
本身作为引用,以便在我调用item
时类型u8
,或者在比较时需要取消引用item
,以便item
= &u8
-> *item
= u8
。>
当我使用(i, &item)
运行代码时,稍后再调用item
时,这与第二个示例中的取消引用是完全一样的,还是在方式上存在根本差异?编译器正在解释第一个代码段和第二个代码段?
第三个代码段有什么问题吗?我意识到这是一个基于意见的问题。我意识到,如果我要使用item
(或*item
来给另一个变量赋值,或者将值赋给引用),则稍后将返回不同的数据类型。除了管理数据类型之外,在考虑item == &b' '
是否是完成工作的正确工具时,还有其他需要牢记的地方吗?
答案 0 :(得分:4)
这些摘要之间没有任何区别。他们生成完全相同的程序集:
pub fn a(bytes: &[u8]) -> usize {
for (i, item) in bytes.iter().enumerate() {
if *item == b' ' {
return i;
}
}
0
}
pub fn b(bytes: &[u8]) -> usize {
for (i, &item) in bytes.iter().enumerate() {
if item == b' ' {
return i;
}
}
0
}
pub fn c(bytes: &[u8]) -> usize {
for (i, item) in bytes.iter().enumerate() {
if item == &b' ' {
return i;
}
}
0
}
playground::a:
negq %rsi
movq $-1, %rax
.LBB0_1:
leaq (%rsi,%rax), %rcx
cmpq $-1, %rcx
je .LBB0_2
cmpb $32, 1(%rdi,%rax)
leaq 1(%rax), %rax
jne .LBB0_1
retq
.LBB0_2:
xorl %eax, %eax
retq
; The code is identical so we just call the existing function
playground::b:
jmp playground::a@PLT
; The code is identical so we just call the existing function
playground::c:
jmp playground::a@PLT
对于它的价值,我将其编写为
pub fn a(bytes: &[u8]) -> Option<usize> {
bytes.iter().position(|&b| b == b' ')
}
iter()
[...]对在bytes
中找到的元素的引用
是的,iter
通常是一个返回引用迭代器的函数。
我需要在两者之间进行比较
通常,您需要在两件事with the same amount of references之间或有时在一个参考差异水平之间进行比较。如何实现此目标无关紧要-引用一个值或取消引用另一个值,或通过*
作为表达式或通过&
取消引用在模式中。
另请参阅: