操作符的trait

Category Trait Operator
Unary operators std::ops::Neg -x
std::ops::Not !x
Arithmetic operators std::ops::Add x + y
std::ops::Sub x - y
std::ops::Mul x * y
std::ops::Div x / y
std::ops::Rem x % y
Bitwise operators std::ops::BitAnd x & y
std::ops::BitOr x | y
std::ops::BitXor x ^ y
std::ops::Shl x << y
std::ops::Shr x >> y
Compound assignment
arithmetic operators
std::ops::AddAssign x += y
std::ops::SubAssign x -= y
std::ops::MulAssign x *= y
std::ops::DivAssign x /= y
std::ops::RemAssign x %= y
Compound assignment
bitwise operators
std::ops::BitAndAssign x &= y
std::ops::BitOrAssign x |= y
std::ops::BitXorAssign x ^= y
std::ops::ShlAssign x <<= y
std::ops::ShrAssign x >>= y
Comparison std::cmp::PartialEq x == y, x != y
std::cmp::PartialOrd x < y, x <= y, x > y, x >= y
Indexing std::ops::Index x[y], &x[y]
std::ops::IndexMut x[y] = z, &mut x[y]

运算和比较

+操作符可以用来将StringString&str拼接到一起,但不允许&str作为+的左操作数,因为讲多个&str拼接到一起性能极差。

运算操作符会取变量的值,而比较操作符是取引用。

相等比较为什么是PartialEq,因为在数学里,相等要满足3个条件:

  • 如果x == y那y == x也要成立,交换性。
  • 如果x == y且y == z,那x == z也要成立, 传递性。
  • x == x必须成立。

因为Rust的浮点数是按照IEEE标准实现的,而IEEE标准要求必须有一个NaN值,而这个NaN值必须和任何值都不相等,包括自己。所以rust只满足前两个条件,所以是PartialEq。但还有另外一个traitEq是完全满足以上条件的,rust的数字类型初浮点数意外都实现了Eq。而且EqPartialEq的subtrait。

PartialOrdPartialEq的subtrait,能比较大小的值也必须能判断相等。PartialOrd必须实现的方法是partial_cmppartial_cmp返回一个Option<Ordering>

  1. enum Ordering {
  2. Less, // self < other
  3. Equal, // self == other
  4. Greater, // self > other
  5. }

如果Option的值是None,说明两个值不能比较大小,也不相等,是无序的。在Rust的所有基础类型中,只有浮点数有可能返回None,也就是比较NaN的时候。
和相等一样也有一个Ord trait,实现了这个trait的类型不会返回Option而是直接返回Ordering,认为比较永远会有结果。和相等一样也是出了浮点数都实现了Ord。

索引操作符

索引操作符由两个trait实现:std::ops::Indexstd::ops::IndexMut,他们需要实现的方法分别是indexindex_mut

  1. trait Index<Idx> {
  2. type Output: ?Sized;
  3. fn index(&self, index: Idx) -> &Self::Output;
  4. }
  5. trait IndexMut<Idx>: Index<Idx> {
  6. fn index_mut(&mut self, index: Idx) -> &mut Self::Output;
  7. }

索引的类型是泛型,因为可以想普通数组取单个元素那样用usize做索引,也可以像取slice那样用Range做索引。HashMap用hashable做索引,BTreeMap用Ordered做索引。
map类没有实现IndexMut,所以m["十"] = 10的直接赋值是不能的。因为index_mut返回的是一个引用,想要有引用就必须先有一个值,所以就得先初始化一个值,但赋值操作马上就赋了一个新值,那刚初始化的那个值又要被丢弃,这样的操作太浪费。这也是IndexMut的一个不足。