为什么不鼓励接受对字符串(& 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?

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

问题描述

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

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

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

我也编写了引用<$ c的代码$ c> Vec 或 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. 使用<$ c $的主要原因之一c> String 或 Vec 是因为它们允许增加或减少容量。但是,当您接受不可变的引用时,就不能在 Vec String 上使用任何有趣的方法。

  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.

    相反,您应该接受字符串切片& str ),切片& [T] )或参考(& T )。 & String & Vec< T> & Box< T> 将自动强制为& 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 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 分配的 String 总价可以通过引用数组来调用(& [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.

    如果您想要从 String Vec< T> 添加或删除项目,可以使用可变引用& mut字符串& Vec< T> ):

    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();
        }
    }
    

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

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