Rust中&符号'&'和星'''符号的含义

Joh*_*nal 16 reference ampersand dereference rust

尽管通读文件,我比较困惑的含义&*象征拉斯特,以及更普遍的关于什么是防锈参考准确.

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

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

但是,以下代码的工作方式完全相同:

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

*在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);
}
Run Code Online (Sandbox Code Playgroud)
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`
Run Code Online (Sandbox Code Playgroud)

但这有效:

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

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

oli*_*obk 19

在C++中使用*来取消引用引用是不正确的.所以我想了解为什么在Rust中这是正确的.

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

C++指针和Rust引用之间的区别在于Rust的引用永远NULL不会是未初始化的,永远不会悬空.


Add特性实现(参见文档页面的底部)以下对和所有其他数字原语:

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

这只是std-lib开发人员实现的一个方便的事情.编译器可以发现a &mut i32可以在任何可以使用的地方&i32使用,但是对于泛型不起作用(但是?),因此std-lib开发人员还需要实现Add以下组合的特征(以及所有原语):

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

正如你所看到的那样,可能会失控.我相信将来会消失.在此之前,请注意,最终只能&mut i32尝试在数学表达式中使用它.

  • 谢谢,我现在明白了。实际上,我曾认为它可能是这样的,但我已经驳回了这个想法,认为用这样的整数地址定义整数的总和会很奇怪。也许应该在文档中强调 Rust 引用被认为是地址,而不是与 C++ 引用混淆。再次感谢您的详细解释。 (2认同)

mb2*_*b21 6

此答案适用于那些寻求基础知识的人(例如,来自Google)。

从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()
}
Run Code Online (Sandbox Code Playgroud)

这些“&”号是参考,它们使您可以引用某些值而不用拥有它的所有权(即借用)。

使用&进行引用的反义词是解引用,这是通过解引用运算符来完成的*

还有一个基本的例子:

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

assert_eq!(5, x);
assert_eq!(5, *y); // dereference y
Run Code Online (Sandbox Code Playgroud)

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

(您可以在“ 智能指针”一章中阅读更多内容。)

方法语法

Rust具有称为自动引用和取消引用的功能。调用方法是Rust少数具有这种行为的地方之一。

下面是它如何工作的:当你调用一个方法有object.something()锈会自动添加&&mut*使物体的方法的签名相匹配。换句话说,以下是相同的:

p1.distance(&p2);
(&p1).distance(&p2);
Run Code Online (Sandbox Code Playgroud)

  • 是的,没有错字。如果你的意思是“self”带有“第一个参数‘distance’”,那么是的。 (2认同)

Jas*_*cha 5

从文档中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
Run Code Online (Sandbox Code Playgroud)

数字的二元 + 运算符似乎是针对操作数的共享(但不可变)引用和操作数的拥有版本的组合来实现的。它与自动取消引用无关。