从不可变数组获取可变引用

问题描述 投票:-1回答:1

我不知道标题是否正确,但这是问题所在:

let mut rows: Vec<Box<String>> = vec![];

let row1 = &mut **rows.get(0).unwrap();

我想存储对多个字符串的可变引用,这些字符串存储在向量的框中。这应该是绝对安全的,因为我没有引用向量中的任何内容,只是从向量中获取一个框,对其进行解引用并更改其指向的内存。如果向量太大,需要重新分配其数据,我的字符串将保持不变。但是rust的编译器不允许我这样做,我得到了错误cannot borrow data in a '&' reference as mutable

我该如何设计?

我可以使rows可变并使用get_mut,但是例如,我将无法同时具有对两行的可变引用:

let mut rows: Vec<Box<String>> = vec![];

let row1 = &mut **rows.get_mut(0).unwrap();
let row2 = &mut **rows.get_mut(1).unwrap();

*row1 = String::from("aaa");
*row2 = String::from("bbb");

这得到cannot borrow 'rows' as mutable more than once at a time

另一种解决方案是仅在需要使用它时才获取每一行,然后在需要再次使用它时再次获取它,但是我认为这不是一个非常有效的主意,因为我必须遍历数组,每次需要更改某些内容时都可以找到我想要的行(我不会通过索引来获取数组元素)。

EDIT:由于Rust的编译器不允许我这样做,因此我试图围绕存储对字符串的可变引用进行设计。我可能缺少一些可以对字符串进行可变引用的方法,或者我需要找到另一种方法来实现这一点。我需要对盒子包含的内容进行可变的引用,在我的程序中它们不是字符串,而是具有可变功能的结构,但是为了简单起见,在这里我使用了字符串。这里有一些代码可以澄清它

struct Table
{
    cols: Vec<Box<Col>>
}

//...

let mut table = Table::new();

let mut id_col          = table.new_col("ID"        .to_owned());
let mut status_col      = table.new_col("Status"    .to_owned());
let mut title_col       = table.new_col("Title"     .to_owned());
let mut deadline_col    = table.new_col("Deadline"  .to_owned());
let mut tags_col        = table.new_col("Tags"      .to_owned());
let mut repeat_col      = table.new_col("Repeat"    .to_owned());

(我在第一个示例中使用了行,以使其更易于理解)我将遍历一些数据并将内容添加到这些列,因此,我不想在每次迭代中在向量中按名称搜索它们,而是希望对它们进行“缓存”引用(所有这些变量) 。问题是我的编译器不允许我这样做,因为我不能多次借用可变表。所以我的意思是“围绕设计”改变了我的思维方式和代码重组,因此我没有这个问题。

rust borrow-checker
1个回答
0
投票
我想存储对多个字符串的可变引用,这些字符串存储在向量的框中。这应该是绝对安全的,因为我没有引用向量中的任何内容,只是从向量中获取一个框,对其进行解引用并更改其指向的内存。如果向量太大,需要重新分配其数据,我的字符串将保持不变。
编译器实际上对此一无所知,也没有确定性:在您的方案中,没有什么可以阻止在同一框或字符串上获得第二个可变句柄并破坏

that。

RefCell在这种情况下存在(“内部可变性”是您要寻找的概念),它暗示着运行时性能受到影响,因为它需要跟踪现有借用(它基本上是单线程RWLock )。

我可以使行可变并使用get_mut,但是例如,我将无法同时对两行进行可变引用

这就是split_mut(和朋友)的目的。

((我在第一个示例中使用行是为了使其更容易理解)我将遍历一些数据并将内容添加到这些列中,因此,我不想在每次迭代中在向量中按名称搜索它们,我希望有对它们的“缓存”引用(所有这些变量)。问题是我的编译器不允许我这样做,因为我不能多次借用可变表。所以我的意思是“围绕设计”改变了我的思维方式和代码重组,因此我没有这个问题。

是的,不仅在集合的各个部分上具有可变的句柄,而且还具有可变的句柄

同时修改父级。您可能需要Rc(而不是Box)和RefCell(用于内部可变性)。

或者进行第二次split_first_mut或展开的迭代器:

let mut t = table.cols.iter_mut(); let id_col = t.next().unwrap(); let status_col = t.next().unwrap(); let title_col = t.next().unwrap(); let deadline_col = t.next().unwrap(); let tags_col = t.next().unwrap(); let repeat_col = t.next().unwrap();

存在以下问题,直到所有这些引用都失效,您才能修改table。而且这很丑。

© www.soinside.com 2019 - 2024. All rights reserved.