我不知道标题是否正确,但这是问题所在:
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());
(我在第一个示例中使用了行,以使其更易于理解)我将遍历一些数据并将内容添加到这些列,因此,我不想在每次迭代中在向量中按名称搜索它们,而是希望对它们进行“缓存”引用(所有这些变量) 。问题是我的编译器不允许我这样做,因为我不能多次借用可变表。所以我的意思是“围绕设计”改变了我的思维方式和代码重组,因此我没有这个问题。
编译器实际上对此一无所知,也没有确定性:在您的方案中,没有什么可以阻止在同一框或字符串上获得第二个可变句柄并破坏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
。而且这很丑。