Why is it discouraged to accept a reference to a String (&String), Vec (&Vec), or Box (&Box) as a function argument?

前端 未结 2 1074
灰色年华
灰色年华 2020-11-21 05:39

I wrote some Rust code that takes a &String as an argument:

fn awesome_greeting(name: &String) {
    println!(\"Wow, you are awesome, {         


        
2条回答
  •  予麋鹿
    予麋鹿 (楼主)
    2020-11-21 06:10

    In addition to Shepmaster's answer, another reason to accept a &str (and similarly &[T] etc) is because of all of the other types besides String and &str that also satisfy Deref. One of the most notable examples is Cow, which lets you be very flexible about whether you are dealing with owned or borrowed data.

    If you have:

    fn awesome_greeting(name: &String) {
        println!("Wow, you are awesome, {}!", name);
    }
    

    But you need to call it with a Cow, you'll have to do this:

    let c: Cow = Cow::from("hello");
    // Allocate an owned String from a str reference and then makes a reference to it anyway!
    awesome_greeting(&c.to_string());
    

    When you change the argument type to &str, you can use Cow seamlessly, without any unnecessary allocation, just like with String:

    let c: Cow = Cow::from("hello");
    // Just pass the same reference along
    awesome_greeting(&c);
    
    let c: Cow = Cow::from(String::from("hello"));
    // Pass a reference to the owned string that you already have
    awesome_greeting(&c);
    

    Accepting &str makes calling your function more uniform and convenient, and the "easiest" way is now also the most efficient. These examples will also work with Cow<[T]> etc.

提交回复
热议问题