为什么我需要在比较变量时取消引用变量而不是在进行算术运算时?
Why do I need to dereference a variable when comparing it but not when doing arithmetic?
我有以下代码:
fn example(known_primes: &[i32], number: i32, prime: i32, limit: i32) {
let mut is_prime = true;
for prime in known_primes {
if number % prime == 0 {
is_prime = false;
break;
}
if *prime > limit {
break;
}
}
}
为什么我需要在第二种情况 (*prime > limit
) 中取消引用 prime
,而在第一种情况 (number % prime == 0
) 中不需要这样做?
%
和 <
都是运算符,它们接受两个数字和 return 一些东西。唯一的区别似乎在于它们 return(数字与布尔值)。虽然 确实 解释了使代码工作所需的条件(所有重载的实现,最好在标准库中),但它 不会 说明为什么它对 a % b
有效。这些运算符之间有根本区别吗?还是还没有实施?
因为您可以 Rem
实现不同类型和核心库实现
impl<'a> Rem<&'a i32> for i32 { /* … */ }
这对于 PartialOrd
和 Ord
特征是不可能的,所以你需要比较完全相同的类型,在本例中 i32
,这就是为什么需要取消引用。
比较运算符的行为实际上与算术运算符不同。当查看特征定义时,差异变得很明显。例如,这里是 PartialEq
特征
pub trait PartialEq<Rhs = Self>
where
Rhs: ?Sized,
{
fn eq(&self, other: &Rhs) -> bool;
fn ne(&self, other: &Rhs) -> bool { ... }
}
和Add
特征
pub trait Add<RHS = Self> {
type Output;
fn add(self, rhs: RHS) -> Self::Output;
}
我们可以看到比较特征通过引用获取操作数,而算术特征通过值获取操作数。这种差异反映在编译器如何翻译运算符表达式上:
a == b ==> std::cmp::PartialEq::eq(&a, &b)
a + b ==> std::ops::Add::add(a, b)
比较的操作数被评估为位置表达式,因此它们永远不能移动值。另一方面,算术运算符的操作数被评估为值表达式,因此根据操作数类型是否为 Copy
.
来移动或复制它们
由于这种差异,如果我们为类型 A
实现 PartialEq
,我们不仅可以比较 A
和 A
,还可以 &A
和 &A
由于操作数的解引用强制。另一方面,对于 Add
我们需要一个单独的实现来添加 &A
和 &A
.
我无法回答为什么标准库实现 "mixed" 版本用于算术运算符的引用和值,而不是用于比较。我看不出后者无法完成的根本原因。
我有以下代码:
fn example(known_primes: &[i32], number: i32, prime: i32, limit: i32) {
let mut is_prime = true;
for prime in known_primes {
if number % prime == 0 {
is_prime = false;
break;
}
if *prime > limit {
break;
}
}
}
为什么我需要在第二种情况 (*prime > limit
) 中取消引用 prime
,而在第一种情况 (number % prime == 0
) 中不需要这样做?
%
和 <
都是运算符,它们接受两个数字和 return 一些东西。唯一的区别似乎在于它们 return(数字与布尔值)。虽然 a % b
有效。这些运算符之间有根本区别吗?还是还没有实施?
因为您可以 Rem
实现不同类型和核心库实现
impl<'a> Rem<&'a i32> for i32 { /* … */ }
这对于 PartialOrd
和 Ord
特征是不可能的,所以你需要比较完全相同的类型,在本例中 i32
,这就是为什么需要取消引用。
比较运算符的行为实际上与算术运算符不同。当查看特征定义时,差异变得很明显。例如,这里是 PartialEq
特征
pub trait PartialEq<Rhs = Self>
where
Rhs: ?Sized,
{
fn eq(&self, other: &Rhs) -> bool;
fn ne(&self, other: &Rhs) -> bool { ... }
}
和Add
特征
pub trait Add<RHS = Self> {
type Output;
fn add(self, rhs: RHS) -> Self::Output;
}
我们可以看到比较特征通过引用获取操作数,而算术特征通过值获取操作数。这种差异反映在编译器如何翻译运算符表达式上:
a == b ==> std::cmp::PartialEq::eq(&a, &b)
a + b ==> std::ops::Add::add(a, b)
比较的操作数被评估为位置表达式,因此它们永远不能移动值。另一方面,算术运算符的操作数被评估为值表达式,因此根据操作数类型是否为 Copy
.
由于这种差异,如果我们为类型 A
实现 PartialEq
,我们不仅可以比较 A
和 A
,还可以 &A
和 &A
由于操作数的解引用强制。另一方面,对于 Add
我们需要一个单独的实现来添加 &A
和 &A
.
我无法回答为什么标准库实现 "mixed" 版本用于算术运算符的引用和值,而不是用于比较。我看不出后者无法完成的根本原因。