Dump of assembler code for function hello_cargo::main: src/main.rs: 1 fn main() { 0x000055555555b6c0 <+0>: sub $0x10,%rsp 2 leta = 0; 0x000055555555b6c4 <+4>: movl $0x0,0x4(%rsp)
zerun.dong$ cargo run Compiling hello_cargo v0.1.0 (/Users/zerun.dong/code/rusttest/hello_cargo) error[E0597]: `x` does not live long enough --> src/main.rs:5:13 | 5 | y = &x; | ^^ borrowed value does not live long enough 6 | } | - `x` dropped here while still borrowed 7 | 8 | println!("{}", y); | - borrow later used here
error: aborting due to previous error
这个例子执行会报错,原因显而易见,y 要引用变量 x, 但是 x 在语句块 {} 中,离开这个词法作用域后就失效了,y 就成了悬垂空引用肯定不行。
1 2 3 4 5 6
fnmain(){ letmut a = String::from("hello"); let a_ref = &mut a; println!("a is {}", a); a_ref.push('!'); }
1 2 3 4 5 6 7 8 9 10 11
zerun.dong$ cargo run Compiling hello_cargo v0.1.0 (/Users/zerun.dong/code/rusttest/hello_cargo) error[E0502]: cannot borrow `a` as immutable because it is also borrowed as mutable --> src/main.rs:4:25 | 3 | let a_ref = &mut a; | ------ mutable borrow occurs here 4 | println!("a is {}", a); | ^ immutable borrow occurs here 5 | a_ref.push('!'); | ----- mutable borrow later used here
上面的代码,a_ref 是可变借用,然后调用 a_ref.push 修改字符串,同时第 4 号要打印原来的 owner a, 这时报错
原因在于,a_ref 是可变借用,在他的的作用域内,不允许存在其它不可变借用或是可变借用,这里 println! 是对 a 的不可变借用
fnmain(){ letmut a = String::from("hello"); let a_ref = &mut a; a_ref.push('!'); println!("a is {}", a); }
1 2 3 4 5
zerun.dong$ cargo run Compiling hello_cargo v0.1.0 (/Users/zerun.dong/code/rusttest/hello_cargo) Finished dev [unoptimized + debuginfo] target(s) in1.51s Running `target/debug/hello_cargo` a is hello!
经过修改之后,把 println 放到 push 后面就可以了
容易困惑的点
一个结构体里也会有引用,初学都很容易晕
1 2 3 4
structStu{ Age: int32 Name: &str }
这里面 Name 是一个字符串的引用,所以实例化的 Stu 对象没有 Name 的所有权,那么就要符合上面的借用规则。说白了,就是内容谁负责释放的问题
impl Number { fnget_num(self) -> u8 { self.num } }
fnmain(){ let num = Number{num:10}; println!("get num {}", num.get_num()); println!("get num {}", num.get_num()); }
上面代码很简单,Number 类型有一个 get_num 方法获取变量 num 值,但是 main 如果调用两次 println 编译时就会报错
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
zerun.dong$ cargo run Compiling hello_cargo v0.1.0 (/Users/zerun.dong/code/rusttest/hello_cargo) error[E0382]: use of moved value: `num` --> src/main.rs:15:28 | 13 | let num = Number{num:10}; | --- move occurs because `num` has type `Number`, which does not implement the `Copy` trait 14 | println!("get num {}", num.get_num()); | --------- `num` moved due to this method call 15 | println!("get num {}", num.get_num()); | ^^^ value used here aftermove | note: this function consumes the receiver `self` by taking ownership of it, which moves `num` --> src/main.rs:7:16 | 7 | fn get_num(self) -> u8 { | ^^^^
可以看到编译器给了提示,因为 get_num(self) 定义为 self 就会 takeing ownership, which moves num
所以类型方法的第一个参数要用引用,写 Go 的人肯定容易蒙蔽。同理还有 match 的匹配语句块,也会 move 对像,需要引用