函数返回不可变引用,但借用检查器认为不然

2023-11-29

在这里,我将一些可变引用传递到函数中以对这些引用执行某些操作。然后,我通过将这些可变引用转变为不可变引用来删除它们。然而,Rust 借用检查器似乎仍然认为它们是可变的。这是代码:

//! src/lib.rs
fn append_1_to_all(strings: Vec<&mut String>) -> Vec<&mut String> {
    strings.into_iter().map(|s| { s.push_str("1"); s }).collect()
}

fn get_shared_references(strings: Vec<&mut String>) -> Vec<&String> {
    strings.into_iter().map(|c| &(*c)).collect()
}

#[test]
fn test() {
    let strings = vec!["one".to_string(), "two".to_string(), "three".to_string()];
    let strings_appended = append_1_to_all(strings.iter_mut().collect());

    let strings_shared = get_shared_references(strings_appended);

    assert_ne!(strings[0], *strings_shared[0]);
}

编译错误:

error[E0502]: cannot borrow `strings` as immutable because it is also borrowed as mutable
  --> src/lib.rs:16:16
   |
12 |     let strings_appended = append_1_to_all(strings.iter_mut().collect());
   |                                            ------- mutable borrow occurs here
...
16 |     assert_ne!(strings[0], *strings_shared[0]);
   |                ^^^^^^^      -------------- mutable borrow later used here
   |                |
   |                immutable borrow occurs here

我该如何修复这个错误?我会想strings_shared不应该再与可变借用相关。


问题不在于您的引用实际上是可变的,而是它使可变引用保持活动状态。

如果您有参考,请输入&'a ... or &'a mut ...,并且您使用它生成另一个引用,无论这是否是重新借用&*some_reference或现场访问&some_struct_reference.some_field或方法或其他任何东西,那就是always被认为是一个borrow源自该原始引用,要求原始引用与派生引用一样长久。

请注意,在您的函数声明中,

fn get_shared_references(strings: Vec<&mut String>) -> Vec<&String> {...}

如果我们将其更改为写出省略的生命周期,我们会得到:

fn get_shared_references<'a>(strings: Vec<&'a mut String>) -> Vec<&'a String> {...}

为了使这项工作成功,我们必须为结果编写其他一生,&'b String而不是“&”字符串。但这个生命周期是怎样的?它是如何受到限制的?它的持续时间不得超过它所指的值确实如此,但比可变引用长。 Rust 的生命周期系统没有办法表达这一点。侥幸逃脱的是:

fn get_shared_references<'m, 'i: 'm>(strings: Vec<&'m mut String>) -> Vec<&'i String> {...}

但即使你可以用这种类型实现一个函数,它对调用者来说也没有用,因为他们不知道关于生命周期的任何事情'i除了“至少只要'm".

我们可以想象一个系统,其中可变引用具有两个生命周期 - 让我们假设语法&'m mut 'i T, where 'm是引用可变的生命周期,并且'i是(不长于)值的生命周期。在这种情况下,我们可能有

fn consumes_mut_ref_produces_ref<'m, 'i>(x: &'m mut 'i i32) -> &'i i32 {...}

但必须设计一套全新的生命周期规则才能使这项工作发挥作用,而且甚至可能无法始终如一地做到这一点。这当然不是今天的 Rust 支持的。


在没有关于您想要做什么的更多详细信息的情况下,我的建议是使此代码能够工作owned价值观。拥有的值可以按照您尝试的方式传递 - 因为将它们作为函数参数转移所有权,因此无需担心生命​​周期,并且更有可能说:“我的函数消耗这个并产生那个”,没有强制关系。

fn append_1_to_all(mut strings: Vec<String>) -> Vec<String> {
    for s in strings.iter_mut() {
        s.push_str("1")
    }
    strings
}

fn get_shared_references(strings: &Vec<String>) -> Vec<&String> {
    // Or even better, just use strings.iter() instead of this function
    strings.iter().collect()
}

#[test]
fn test() {
    let strings = vec!["one".to_string(), "two".to_string(), "three".to_string()];

    // .clone() here is necessarily only because strings is used in the assert below
    let strings_appended = append_1_to_all(strings.clone());

    let strings_shared = get_shared_references(&strings_appended);

    assert_ne!(strings[0], *strings_shared[0]);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

函数返回不可变引用,但借用检查器认为不然 的相关文章

随机推荐

  • 在子目录中设置 CakePHP; WordPress 安装在根目录下

    我已经寻找解决方案两个小时了 但似乎没有任何效果 这是我的问题 我已将 WordPress 安装在根目录 var www 中 所以通过去http www geekderek com 我看到我的 WordPress 网站 我将 CakePHP
  • 如何从代码中执行onTouch事件?

    Using myObject performClick 我可以从代码中模拟点击事件 像这样的东西存在吗onTouch事件 我可以通过 Java 代码模仿触摸操作吗 EDIT 这是我的onTouch听众 myObject setOnTouch
  • gcc 相当于#pragma comment

    我正在尝试编写一个宏 使用 gcc 编译器向可执行文件添加注释 这不是为了链接目的 我只是想添加文字评论 gcc 中是否有用于此目的的 pragma comment 等效项 我不确定 向可执行文件添加注释 是什么意思 谁或什么会消费 展示甚
  • SIMD 的优先选择是始终摆脱分支吗?

    如果您正在编写一些将由另一个程序运行的 SIMD 代码 那么摆脱分支以提高性能是否总是有利的 我听说甚至做额外的操作只是为了避免if else语句等仍然快得多 我问这个是因为我做了一些分支 基本上是这样的 axis x 0 y 1 z 2
  • 从列表框用户表单中删除一行

    我有一个列表框 显示 Excel 工作表的行 我需要添加一个删除按钮来删除所选行 我试过这个 Private Sub CommandButton3 Click Dim i As Integer For i 0 To Range A65356
  • 如何从 PHP 中 var_dump 的输出创建数组?

    我怎样才能解析输出var dump在 PHP 中创建数组 Use 变量导出如果你想要一个也是有效 PHP 代码的表示 a array 1 2 array a b c dump var export a true echo dump 将显示
  • AVAudioPlayer 的 NSOSStatusErrorDomain 代码=-54

    AVAudioPlayer 在某些本地 MP3 文件上出现以下错误 Error Domain NSOSStatusErrorDomain Code 54 null 我正在将 zip 文件下载到 Documents 目录 然后使用名为的库解压
  • 从 NSMutableArray 中删除 for 循环中的对象

    我正在与一个UITableView对于作为数据源的数组中的每个对象UITableView 如果它们符合某个条件我就会删除它们if陈述 我的问题是它只删除数组中的所有其他对象 Code UIImage isCkDone UIImage ima
  • 为什么 C++ 中存在从指针到 bool 的隐式类型转换?

    考虑班级foo有两个这样定义的构造函数 class foo public foo const std string filename std cout lt lt ctor 1 lt lt std endl foo const bool s
  • 如何在 Android 上将 TTS 输出保存为音频文件?

    这是我在此的头一篇博文 我是 Android 编程新手 我想创建一个应用程序 可以将文本到语音的输出保存到音频文件中到我的数据库中 我听说过合成到文件 但事实并非如此 SynthesizeToFile 应该创建一个 wav 您可以解码并发送
  • 下拉菜单 - 使

    我有点疯狂地试图实现我的客户想要的东西 我可以告诉他们这是不可能的 但我喜欢挑战 基本上 我正在尝试做一个下拉菜单 其中下拉菜单 ul or ul menu li ul 被 div 包围 有点儿 ul class menu li a hre
  • Django get_object_or_404() 与 DateTimeField

    我现在正在读 Django by Example 一书 我在使用参数查找记录时遇到问题 我的代码如下所示 设置 py TIME ZONE Asia Seoul 模型 py published models DateTimeField def
  • 关闭所有打开视图控制器的单一函数

    我有一个应用程序 它是单视图应用程序 我有一个导航控制器链接到根视图控制器的所有子控制器 在每个子控制器中 我都有一个注销按钮 我想知道是否可以有一个可以调用的函数 该函数将关闭一路上打开的所有控制器 无论用户按下注销时当前打开哪个控制器
  • 如何从 Python 集合中随机选择 2 个项目? [复制]

    这个问题在这里已经有答案了 我目前有一个 n 大小的 Python 集 其中 n gt 0 是否有一个快速的 1 或 2 行 Python 解决方案可以做到这一点 例如 该集合将如下所示 fruits set apple orange wa
  • Java 线程中的“阻塞计数”和“等待计数”是什么意思?

    我使用 JConsole 来观看线程 它显示 name Thread 6 state BLOCKED sun misc Launcher AppClassLoader 19821f owner Thread 3 blocked Count
  • 由于“拒绝连接”,我无法使用 MySQL

    我正在尝试在 Windows XP 上运行 MySQL 的免安装版本 位于C mysql 在我的机器上 当我尝试连接到 MySQL 时 我在 PHP 文件中收到错误消息 无法连接 无法连接 因为目标机器主动拒绝 我已经编辑了配置文件my i
  • 未定义的属性: Illuminate\Database\Eloquent\Collection:: Laravel 5.2

    我试图让物联网显示订单中的商品 但我不断收到此错误 这些是我的模型 class westcoorder extends Model protected table westcoorders protected with westcoorde
  • 如何将线程函数的地址作为回调传递给winapi?

    我有一个简单的线程 在执行过程中我尝试使用线程中定义的函数之一的地址调用 EnumWindows 所以我试图这样做 EnumWindows cbEnumWindowsClickOK 0 其中 cbEnumWindowsClickOK 是在线
  • iOS 如何重新启动应用程序以更改语言 Swift 4

    我使用多语言应用程序 我想在配置文件用户中手动更改语言 我已经有 Localization string 如果我更改设备语言 应用程序中的语言将更改为 但我想从用户配置文件示例中手动更改语言 为此 我使用下一个代码 private func
  • 函数返回不可变引用,但借用检查器认为不然

    在这里 我将一些可变引用传递到函数中以对这些引用执行某些操作 然后 我通过将这些可变引用转变为不可变引用来删除它们 然而 Rust 借用检查器似乎仍然认为它们是可变的 这是代码 src lib rs fn append 1 to all s