为什么不鼓励接受对 String (&String)、Vec (&Vec) 或 Box (&Box) 的引用作为函数参数? [英] Why is it discouraged to accept a reference to a String (&String), Vec (&Vec), or Box (&Box) as a function argument?

查看:14
本文介绍了为什么不鼓励接受对 String (&String)、Vec (&Vec) 或 Box (&Box) 的引用作为函数参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写了一些以 &String 作为参数的 Rust 代码:

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

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

我还编写了引用 VecBox 的代码:

I've also written code that takes in a reference to a Vec or Box:

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

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

但是,我收到了一些反馈,说这样做不是一个好主意.为什么不呢?

However, I received some feedback that doing it like this isn't a good idea. Why not?

推荐答案

TL;DR:可以改用 &str, &[T]&T 以允许使用更通用的代码.

TL;DR: One can instead use &str, &[T] or &T to allow for more generic code.

  1. 使用 StringVec 的主要原因之一是因为它们允许增加或减少容量.然而,当你接受一个不可变的引用时,你不能在 VecString 上使用任何这些有趣的方法.

  1. One of the main reasons to use a String or a Vec is because they allow increasing or decreasing the capacity. However, when you accept an immutable reference, you cannot use any of those interesting methods on the Vec or String.

接受 &String&Vec&Box要求在调用函数之前要在堆上分配的参数.接受 &str 允许字符串文字(保存在程序数据中)并接受 &[T]&T 允许堆栈分配的数组或变量.不必要的分配是一种性能损失.当您尝试在测试或 main 方法中调用这些方法时,通常会立即暴露:

Accepting a &String, &Vec or &Box also requires the argument to be allocated on the heap before you can call the function. Accepting a &str allows a string literal (saved in the program data) and accepting a &[T] or &T allows a stack-allocated array or variable. Unnecessary allocation is a performance loss. This is usually exposed right away when you try to call these methods in a test or a main method:

awesome_greeting(&String::from("Anna"));

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

is_even(&Box::new(42))

  • 另一个性能考虑是 &String&Vec&Box 引入了不必要的间接层,如您必须取消引用 &String 以获得 String,然后执行第二次取消引用以结束 &str.

  • Another performance consideration is that &String, &Vec and &Box introduce an unnecessary layer of indirection as you have to dereference the &String to get a String and then perform a second dereference to end up at &str.

    相反,你应该接受一个 string slice (&str),一个 slice (&[T]),或者只是一个参考(&T).&String&Vec&Box 将被自动强制(通过 deref coercion) 到 &str&[T]&T,分别.

    Instead, you should accept a string slice (&str), a slice (&[T]), or just a reference (&T). A &String, &Vec<T> or &Box<T> will be automatically coerced (via deref coercion) to a &str, &[T] or &T, respectively.

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

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

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

    现在您可以使用更广泛的类型集调用这些方法.例如,awesome_greeting 可以用字符串文字(Anna")分配的 String 调用.total_price 可以通过引用数组 (&[1, 2, 3]) 一个分配的 Vec.

    Now you can call these methods with a broader set of types. For example, awesome_greeting can be called with a string literal ("Anna") or an allocated String. total_price can be called with a reference to an array (&[1, 2, 3]) or an allocated Vec.

    如果您想从 StringVec 中添加或删除项目,您可以使用 可变引用 (&mut String&mut Vec):

    If you'd like to add or remove items from the String or Vec<T>, you can take a mutable reference (&mut String or &mut Vec<T>):

    fn add_greeting_target(greeting: &mut String) {
        greeting.push_str("world!");
    }
    

    fn add_candy_prices(prices: &mut Vec<i32>) {
        prices.push(5);
        prices.push(25);
    }
    

    特别是对于切片,您还可以接受 &mut [T]&mut str.这允许您改变切片内的特定值,但您不能更改切片内的项目数(这意味着它对字符串非常有限):

    Specifically for slices, you can also accept a &mut [T] or &mut str. This allows you to mutate a specific value inside the slice, but you cannot change the number of items inside the slice (which means it's very restricted for strings):

    fn reset_first_price(prices: &mut [i32]) {
        prices[0] = 0;
    }
    

    fn lowercase_first_ascii_character(s: &mut str) {
        if let Some(f) = s.get_mut(0..1) {
            f.make_ascii_lowercase();
        }
    }
    

    这篇关于为什么不鼓励接受对 String (&amp;String)、Vec (&amp;Vec) 或 Box (&amp;Box) 的引用作为函数参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    相关文章
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆