Chapter 5. Why It’s Discouraged to Accept a Reference to a String, Vec, or Box as a Function Parameter

 

Here’s some Rust code that takes a &String as a parameter:

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

And here’s code that takes a reference to a Vec:

fn total_price(prices: &Vec) -> i32 {
        prices.iter().sum()
}

And code that takes a reference to a Box:

fn is_even(value: &Box) -> bool {
        **value % 2 == 0
}

These function definitions work, but they’re not idiomatic Rust. The reason is that we can instead define functions to use &str, &[T] or &T as parameter types with no loss of genericity. Let’s explore further.

One of the main reasons to use a String or a Vec is because they allow increasing or decreasing the capacity. However, when we use an immutable reference as a parameter type in a function definition, that function can’t use any of those interesting methods on the Vec or String.

Accepting a &String, &Vec or &Box also requires an allocation before we can call the method. Unnecessary allocation is a performance loss. This is usually exposed right away when we try to call these methods in a test or a main method:

fn main() {
        awesome_greeting(&String;:from("Anna"));

        total_price(&vec![42, 13, 1337])

        is_even(&Box;:new(42))
}