fnmain() { let v1 = 100; let v2 = 100; let a = |x: i32| x; let b = |x: i32| x + v1; let c = |x: i32| x + v1 + v2; assert_eq!(size_of(&a), 0); assert_eq!(size_of(&b), 8); assert_eq!(size_of(&c), 16); }
# cargo run Compiling hello_cargo v0.1.0 (/root/zerun.dong/code/rusttest/hello_cargo) Finished dev [unoptimized + debuginfo] target(s) in 2.35s Running `target/debug/hello_cargo` now a is 3
可以看到,当 inc 执行两次后,a 的结果是 3, 由上面可以知道此时 inc 以引用的方式捕获变量 a
1 2 3 4 5 6
fnmain(){ let s = String::from("test"); let f = || {let _s = s;println!("{}", _s)}; f(); f(); }
这是转移所有权的例子,堆上的字符串变量 s, 所有权转给了闭包中的临时变量 _s
1 2 3 4 5 6
fnmain(){ letmut s = String::from("test"); letmut f = || {s.push('a');println!("{}", s)}; f(); f(); }
例子中闭包 f 修改字符串 s, 并打印
1 2 3 4 5 6
$ cargo run Compiling hello_cargo v0.1.0 (/Users/zerun.dong/code/rusttest/hello_cargo) Finished dev [unoptimized + debuginfo] target(s) in 0.55s Running `target/debug/hello_cargo` testa testaa
执行后打印,输出和预期一样
1 2 3 4 5 6 7 8 9
# cargo run Compiling hello_cargo v0.1.0 (/root/zerun.dong/code/rusttest/hello_cargo) error[E0382]: use of moved value: `f` --> src/main.rs:5:5 | 4 | f(); | --- `f` moved due to this call 5 | f(); | ^ value used here after move
函数只能执行一次,因为当第一次执行时,_s 随后析构释放了内存,所以编译器报错
1 2 3 4 5 6
fnmain(){ let s = String::from("test"); let f = move || {println!("{}", s)}; f(); f(); }
如果想把变量转移给闭包,就需要显示使用 move 关键字,此时字符串 test 所有权转给了闭包 f, 当然可以多次执行,直到 f 离开作用域后一起析构,感兴趣的可以返汇编自己看一下