Rust 中的 & 符号和星号是什么意思?

尽管彻底阅读了文档,但我对 Rust 中 &*符号的含义,以及更一般的 Rust 引用的确切含义感到相当困惑。

在这个例子中,它似乎类似于 C + + 引用(也就是说,使用时自动解引用的地址) :

fn main() {
let c: i32 = 5;
let rc = &c;
let next = rc + 1;
println!("{}", next); // 6
}

然而,以下代码的工作原理完全相同:

fn main() {
let c: i32 = 5;
let rc = &c;
let next = *rc + 1;
println!("{}", next); // 6
}

在 C + + 中,使用 *来取消引用是不正确的。所以我想知道为什么在 Rust 中这是正确的。

到目前为止,我的理解是,在 Rust 引用前插入 *会解除对它的引用,但是 *是隐式插入的,所以你不需要添加它(在 C + + 中,它是隐式插入的,如果你插入它,你会得到一个编译错误)。

然而,这样的东西不能编译:

fn main() {
let mut c: i32 = 5;
let mut next: i32 = 0;
{
let rc = &mut c;
next = rc + 1;
}
println!("{}", next);
}
error[E0369]: binary operation `+` cannot be applied to type `&mut i32`
--> src/main.rs:6:16
|
6 |         next = rc + 1;
|                ^^^^^^
|
= note: this is a reference to a type that `+` can be applied to; you need to dereference this variable once for this operation to work
= note: an implementation of `std::ops::Add` might be missing for `&mut i32`

但这种方法是有效的:

fn main() {
let mut c: i32 = 5;
let mut next: i32 = 0;
{
let rc = &mut c;
next = *rc + 1;
}
println!("{}", next);  // 6
}

似乎隐式解引用(la C + +)对于不可变引用是正确的,但对于可变引用则不是。为什么会这样?

24128 次浏览

在 C + + 中,使用 * 来取消引用是不正确的。所以我想知道为什么在 Rust 中这是正确的。

C + + 中的引用与 Rust 中的引用不同。Rust 的引用更接近于 C + + 的指针(在用法上,而非语义上)。就内存表示而言,Rust 的引用通常只是一个指针,而 C + + 的引用应该是同一对象的替代名称(因此没有内存表示)。

C + + 指针和 Rust 引用之间的区别在于 Rust 的引用从来不是 NULL,从来不是未初始化的,也从来不是悬挂的。


对于以下对和所有其他数字原语,实现了 Add trait (参见文档页面底部) :

  • &i32 + i32
  • i32 + &i32
  • &i32 + &i32

这只是 std-lib 开发人员实现的一个方便之处。编译器可以算出,只要使用 &i32,就可以使用 &mut i32,但是这还不行(还不行?)对于泛型,因此 std-lib 开发人员还需要为以下组合实现 Add trait (以及所有原语的组合) :

  • &mut i32 + i32
  • i32 + &mut i32
  • &mut i32 + &mut i32
  • &mut i32 + &i32
  • &i32 + &mut i32

你也看到了,情况已经失控了。我相信这种情况以后会消失的。在此之前,请注意,以 &mut i32结束并试图在数学表达式中使用它是相当罕见的。

来自 std::ops::Add的文件:

impl<'a, 'b> Add<&'a i32> for &'b i32
impl<'a> Add<&'a i32> for i32
impl<'a> Add<i32> for &'a i32
impl Add<i32> for i32

数字的二进制 + 运算符似乎是为操作数的共享(但不可变)引用和操作数的拥有版本的组合实现的。它与自动解引用没有任何关系。

这个答案是给那些寻找基础知识的人的(例如来自谷歌)。

来自 Rust 书的 参考文献及借用:

fn main() {
let s1 = String::from("hello");


let len = calculate_length(&s1);


println!("The length of '{}' is {}.", s1, len);
}


fn calculate_length(s: &String) -> usize {
s.len()
}

这些与号表示引用,它们允许你引用一些值,而不需要占有它(即借用)。

与使用 &进行引用相反的是使用解引用运算符 *完成的 解除引用

举个简单的例子:

let x = 5;
let y = &x; //set y to a reference to x


assert_eq!(5, x);
assert_eq!(5, *y); // dereference y

如果我们尝试编写 assert_eq!(5, y);,则会得到编译错误 can't compare `{integer}` with `&{integer}`

(详情请参阅 智能指针章节。)

来自 方法语法:

Rust 有一个称为 自动引用和解引用的特性。调用方法是 Rust 中少数几个具有这种行为的地方之一。

它是这样工作的: 当您使用 object.something()调用一个方法时,Rust 会自动添加 &&mut*,以便对象匹配该方法的签名。换句话说,以下内容是相同的:

p1.distance(&p2);
(&p1).distance(&p2);