为什么不鼓励接受引用 &String、&Vec 或 &Box 作为函数参数?

2024-03-23

我写了一些 Rust 代码,需要&String作为一个论点:

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

我还编写了接受对 a 的引用的代码Vec or Box:

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

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

然而,我收到一些反馈说这样做不是一个好主意。为什么不?


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


  1. 使用的主要原因之一String or a Vec是因为它们允许增加或减少容量。但是,当您接受不可变引用时,您无法在Vec or String.

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

    awesome_greeting(&String::from("Anna"));
    
    total_price(&vec![42, 13, 1337])
    
    is_even(&Box::new(42))
    
  3. 另一个性能考虑因素是&String, &Vec and &Box引入不必要的间接层,因为您必须取消引用&String得到一个String然后执行第二次取消引用以结束&str.

相反,您应该接受字符串切片 (&str), a slice (&[T]),或者只是一个参考(&T). A &String, &Vec<T> or &Box<T>将被自动强制(通过解除引用强制 https://doc.rust-lang.org/stable/reference/type-coercions.html#coercion-types) to a &str, &[T] or &T, 分别。

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") or分配的String. total_price可以通过引用数组来调用(&[1, 2, 3]) or分配的Vec.


如果您想添加或删除项目String or Vec<T>,你可以采取可变引用 (&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] or &mut str。这允许您改变切片内的特定值,但无法更改切片内的项目数量(这意味着它对于字符串非常有限):

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();
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么不鼓励接受引用 &String、&Vec 或 &Box 作为函数参数? 的相关文章

随机推荐

  • ggplot2 在函数 R 内时似乎不起作用 [重复]

    这个问题在这里已经有答案了 我对 R 有点陌生 我一直在尝试将 R 脚本包装为函数 以便我可以从 Rserve 调用它 有谁知道为什么 ggplot2 不能在函数内部工作但在函数外部却工作得很好 png polarity png ggplo
  • 围绕其中心点旋转 UIImageView?

    我在 UIImageView 中有一个透明的 png self myImage 我想绕其中心点旋转 代码应该非常简单 self myImage layer setAnchorPoint CGPointMake 0 5 0 5 UIView
  • 在 Win64 下将 SOCKET 转换为 int 安全吗?

    我正在开发 POSIX C 程序的 Windows 端口 问题是标准 POSIX 函数 如accept 或bind 期望 int 作为第一个参数 而其WinSock 对应函数则使用 SOCKET 当编译为 32 位时 一切都很好 因为两者都
  • 获取图像大小而不将图像加载到内存中

    据我所知 您可以通过以下方式使用 PIL 获取图像大小 from PIL import Image im Image open image filename width height im size 但是 我想获取图像的宽度和高度witho
  • 使用 GStreamer 将视频转换为 WebM

    文档用于GStreamer令人困惑 这仍然不是诉诸的借口StackOverflow com 但仍然 是什么GStreamer命令行将任何视频文件 任何格式 转换为 WebM WebM 音频 这是我能找到的唯一带有示例的文档 http gst
  • 使用随机字段解析 JSON (java)

    我想转换一个JSON文件到一个CSV file My JSON文件来自DataBase存储在Firebase并且有这样的结构 PATIENT LbhwHC7Y6 umc age 31 name Phoebe LbhwTFJ6xjEf age
  • 更改 PHP 文件上传的默认临时目录

    我正在本地制作一个网站 允许上传 pdf 文件 当这些文件在本地上传时 它们会转到C xampp tmp但是当我在大学服务器上托管该网站时 我无权访问临时目录 有什么方法可以更改文件的默认临时位置吗 提前致谢 戴夫 可以使用以下命令配置上传
  • 使用 GtkAda 发出信号

    我担心的是我创建了一个回调函数 它应该显示Gtk Entry当我们点击Gtk Button但当我点击按钮时什么也没有发生 我不明白 File ads Package Test is Type T Test is record Contene
  • 在 EasyPHP{WAMP} 中设置 root 密码后无法从 phpMyAdmin 访问 MySQL

    首次启动 MySQL 成功设置后 出于安全原因 页面提示我设置 ROOT 密码 设置密码后 我无法再访问 MySQL 错误是 1045 Access denied for user root localhost using password
  • Asift 和 openCV?

    opencv 允许使用 ASIFT 吗 http www ipol im pub algo my affine sift http www ipol im pub algo my affine sift 作者发布了c 所以我相信将其实现到o
  • 弹性框文本项溢出

    谁能解释一下为什么包含文本的列的宽度没有正确计算以完全包含每列中的文本 在 Firefox 和 Chrome 上 第一列和第三列中的文本不适合这些框 但令人惊讶的是 这些框在 IE 11 中的大小正确 这是浏览器错误吗 box displa
  • Windows 服务 + Windows 窗体应用程序。一个数据库。关于并发的建议

    我有包含文件信息的 SQL Server 数据库 我正在谈论自定义属性 这些是每个文件的类别和描述 Windows 窗体应用程序是供用户使用的 但我还将创建一个 Windows 服务来跟踪文件的任何更改 如果发生更改 重命名 移动 删除 服
  • ASP.NET Core 1.0 中的 AWS Elastic Beanstalk 环境变量

    如何将环境变量从 Elastic beanstalk 获取到 asp net core mvc 应用程序中 我添加了一个 ebextensions 文件夹 其中包含 app config 文件 其中包含以下内容 option setting
  • 将值添加到弧

    我正在尝试向 arc 添加值并为此目的制定了一种方法 然而 即使 for 循环给出了不同的坐标 它们看起来也都在一个地方 可能是什么问题 this RangeEnd 是 float 200 这是添加值的方法 private void OnD
  • 利用浏览器缓存,在 apache 或 .htaccess 上如何?

    在这里做什么 我有一个巨大的文件列表 Google Speed Page 说 利用浏览器缓存 但我不知道如何 我是否会弄乱或更改 Apache 配置文件 如下 或者是否在 htaccess 页面中放置了某些内容
  • 从 Node.js 中的 Array 对象中删除特定属性

    例如我有这个数组 如果我对它进行字符串化 它会是这样的 car Toyota ID 1 Doors 4 price 20 000 car Chevrolet ID 2 Doors 2 price 15 000 我该如何从两辆车中取出 门和价
  • NGramTokenizer 未按预期工作

    我有一个简单的 R 代码 可以从文件中读取文本并在条形图上绘制重复出现的短语 由于某种原因 条形图仅显示单个单词而不是多词短语 我哪里出错了 install packages xlsx install packages tm install
  • 使用自定义字体 pdfmake 进行角度

    我正在关注这个文档 https github com bpampuch pdfmake wiki Custom Fonts client side的自定义字体pdfmake 我无法理解我该如何遵循 Angular 4 的这个例子 因为我的p
  • Clearscript Javascript“需要”功能

    我正在尝试为 Twilio 可编程聊天工具编写 C 包装器 提供的库适用于 JS 客户端 我认为使用像 ClearScript V8 这样的工具可以让我根据需要包装 js 网站上的示例代码是 const Chat require twili
  • 为什么不鼓励接受引用 &String、&Vec 或 &Box 作为函数参数?

    我写了一些 Rust 代码 需要 String作为一个论点 fn awesome greeting name String println Wow you are awesome name 我还编写了接受对 a 的引用的代码Vec or B