Some(v)和Some(&v)之间有什么区别?

huangapple go评论61阅读模式
英文:

What's the difference between Some(v) and Some(&v)?

问题

以下是您要翻译的内容:

`code block 1` 和下面的代码中的 `code block 2` 都有效,但我不知道为什么。
`Some(&number)` 和 `Some(number)` 之间有什么区别?

```rust
use std::collections::HashMap;

fn call(number: &str) -> &str {
    match number {
        "798-1364" => "We're sorry, please hang up and try again.",
        "645-7689" => "Hello, what can I get for you today?",
        _ => "Hi! Who is this again?"
    }
}

fn main() { 
    let mut contacts = HashMap::new();

    contacts.insert("Daniel", "798-1364");

    //====== 代码块 1
    match contacts.get(&"Daniel") {
        Some(&number) => println!("Calling Daniel: {}", call(&number)),
        _ => println!("Don't have Daniel's number."),
    }

    //====== 代码块 2, 没有 '&'
    match contacts.get("Daniel") {
        Some(number) => println!("Calling Daniel: {}", call(number)),
        _ => println!("Don't have Daniel's number."),
    }

}
英文:

Both code block 1 and code block 2 in below code work, but I don't know why.
What's the difference between Some(&number) and Some(number) ?

use std::collections::HashMap;

fn call(number: &str) -> &str {
    match number {
        "798-1364" => "We're sorry, please hang up and try again.",
        "645-7689" => "Hello, what can I get for you today?",
        _ => "Hi! Who is this again?"
    }
}

fn main() { 
    let mut contacts = HashMap::new();

    contacts.insert("Daniel", "798-1364");

    //====== code block 1
    match contacts.get(&"Daniel") {
        Some(&number) => println!("Calling Daniel: {}", call(&number)),
        _ => println!("Don't have Daniel's number."),
    }

    //====== code block 2, without '&'
    match contacts.get("Daniel") {
        Some(number) => println!("Calling Daniel: {}", call(number)),
        _ => println!("Don't have Daniel's number."),
    }

}

答案1

得分: 2

contacts.get("Daniel") 中,参数的类型是 &str

contacts.get(&"Daniel") 中,参数的类型是 &&str

HashMapget() 方法的实现如下:

pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
where
    K: Borrow<Q>,
    Q: Hash + Eq,
{
    self.base.get(k)
}

当您传递 &&str 时,Rust 编译器会自动将 &&str 解引用为 &str。因此,您的两个版本实质上是等价的。

在您的 match 分支 中:

  • Some(&number)number 的类型是 &str
  • Some(number)number 的类型是 &&str

再次提醒,由于 Rust 的自动解引用规则,两者实质上是相同的。

请注意,如果您写成了 Some(&&number)number 的类型将会是 str,并且将会出现以下编译错误信息:

the size for values of type `str` cannot be known at compilation time

但是当您使用 &&T 甚至是 &&&&&T 时,它会起到与 &T 相同的作用。

英文:

In contacts.get("Daniel") the type of the argument is &str.

In contacts.get(&"Daniel") the type of the argument is &&str.

The HashMap's get() method is implemented as follows:

pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
where
    K: Borrow<Q>,
    Q: Hash + Eq,
{
    self.base.get(k)
}

When you pass &&str, the Rust compiler automatically dereferences &&str to &str. As a result, both your versions are essentially equivalent.

In your match arm:

  • Some(&number) the type of number is &str,
  • Some(number) the type of number is &&str.

Again, due to Rust's auto-dereference rules, both are essentially the same.

Note that if you had written Some(&&number), the type of number would have been str and that wouldn't compile with the message:

the size for values of type `str` cannot be known at compilation time

But when you have &&T or even &&&&&T, that acts as if you had &T.

huangapple
  • 本文由 发表于 2023年5月18日 11:34:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/76277559.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定