#[derive(Debug)]

struct WhatAboutThis<'a> {

name: String,

nickname: Option<&'a str>,

}

impl<'a> WhatAboutThis<'a> {

fn tie_the_knot(&'a mut self) {

self.nickname = Some(&self.name[..4]);

}

}

fn main() {

let mut tricky = WhatAboutThis {

name: "Annabelle".to_string(),

nickname: None,

};

tricky.tie_the_knot();

// cannot borrow `tricky` as immutable because it is also borrowed as mutable

// println!("{:?}", tricky);

}

这段代码中如果把最后一句println!("{:?}", tricky)注释放开,为什么会报“cannot borrow tricky as immutable because it is also borrowed as mutable” 与上述代码几乎一样道理的这个:println!("{}",s); 就不报错呢?没搞明白!

fn main() {

let mut s = String::from("hello");

change(&mut s);

println!("{}",s);

}

fn change(some_string: &mut String) {

some_string.push_str(", world");

}

发表一下个人愚见. 有错误还请指出. 问题出在 fn tie_the_knot(&'a mut self) 这里创建了一个可变引用, 且它的生命周期和 struct WhatAboutThis<'a> 是一样长的. 因此在main()中的代码, tricky.tie_the_knot();所隐含创建的可变借用的生命周期和tricky这个struct值的生命周期是一样长的, 都截至到main()函数结尾. 因此编译器可能不太聪明的认为: 在tricky.tie_the_knot(); 之后(main结束前) 都存在一个对tricky的可变借用, 因此不能再创建对tricky的其它借用了. 但println! 会创建一个不可变借用, 因此编译器认为这违反了借用规则.

另一个例子中的change()可以改写成 等价 形式 :

fn change<'a>(some_string: &'a mut String) {

some_string.push_str(", world");

}

区别在于这里的生命周期注解不像上面那个有额外的限制: 'a首先是struct WhatAboutThis的生命周期, 并且也是fn tie_the_knot(&'a mut self) 中隐含创建的可变引用的生命周期.

因此问题在于(在编译器看来)可变引用的生命周期过大了, 进而遇到借用检查的阻挠. 一个解决的办法就是将其改为不可变引用, 但同时也要有能力来修改struct中的nickname字段, 因此要"包裹"一层 RefCell<> :

use std::cell::* ;

#[derive(Debug)]

struct WhatAboutThis<'a> {

name: String,

nickname: RefCell > , // <<======

}

impl<'a> WhatAboutThis<'a>

{

fn tie_the_knot(&'a self) { // <<====== 不可变借用 !

*self.nickname.borrow_mut() = Some(&self.name[..4]);

}

}

fn main() {

let mut tricky = WhatAboutThis {

name: "Annabelle".to_string(),

nickname: RefCell::new(None) , // <<======

};

tricky.tie_the_knot();

println!("===> {:?}", tricky);

}

查看原文