rust_interview
rust_interview copied to clipboard
[Advance] 闭包捕获变量顺序
let c = move || {
{
let y_ref = &y;
}
x; y; z;
};
假如x、y、z都是外部变量,那么上面闭包示例中,是先捕获y呢,还是先捕获z ?析构顺序是什么样的?
这个是按栈的顺序吗? 即 z,y,x -> x,y,z
捕获顺序为 y, x, z, 单纯是按闭包内使用的顺序
析构为 x, y, z, 因为第五行 consume 的顺序是这样的
@iovxw 析构也是y,x,z
@biluohc 你说的是let声明绑定的析构顺序,这里是闭包,略有不同
看来每个issue需要配上play比较好
总感觉莫名其妙,可以写个结构加闭包验证下
https://play.rust-lang.org/?gist=1233af65c31bfb32603d07c10b009ce2&version=stable
你来看看我这个, 呵 https://play.rust-lang.org/?gist=2d780efb162f4e9b5d396f61207c1e9c&version=stable
catch不知道怎么验证, MIR里是这样的, 大概是y,x,z, 即使用顺序.
fn main() -> () {
let mut _0: (); // return pointer
scope 1 {
let _1: PrintDrop; // "y" in scope 1 at src/main.rs:9:9: 9:10
scope 3 {
let _2: PrintDrop; // "x" in scope 3 at src/main.rs:10:9: 10:10
scope 5 {
let _3: PrintDrop; // "z" in scope 5 at src/main.rs:11:9: 11:10
scope 7 {
let _4: [closure@src/main.rs:12:19: 15:6 y:PrintDrop, x:PrintDrop, z:PrintDrop]; // "closure" in scope 7 at src/main.rs:12:9: 12:16
}
scope 8 {
}
}
scope 6 {
}
}
scope 4 {
}
}
scope 2 {
}
let mut _5: PrintDrop;
let mut _6: PrintDrop;
let mut _7: PrintDrop;
let mut _8: ();
let mut _9: [closure@src/main.rs:12:19: 15:6 y:PrintDrop, x:PrintDrop, z:PrintDrop];
let mut _10: ();
@iovxw 谢啦.
@biluohc y,x,z那是捕获顺序。 你这个例子,调用了闭包,是另外一道题了。
那你说说闭包使用与否对析构有什么影响? 因为没有闭包内部的作用域使用, 就按catch顺序drop?
@biluohc 闭包调用确实是有影响的。目前按结果来看是这样。
我去, 还能像css盒子模型那样重合..
闭包调用换成; 就和那个没有使用闭包的一样了. 所以你说的这个坑和这个题没有关系吧.
@biluohc 汗! 那个说法错了,我改了。 不是那个坑的问题。
@biluohc 你可以看看加上闭包调用和不加闭包调用的MIR。
其实闭包没有调用之前,在闭包的MIR里打的drop标记顺序和使用顺序是一致的。 但是这个drop标记是在运行时才执行的,也就是闭包执行才能按这个drop标记析构。 但是如果闭包没有调用,这个drop标记就没用。只能按离开main函数作用域时候的捕获顺序来析构了。
比较闭包调用和没有闭包调用两种情况的MIR,你会发现:
_14 = const std::ops::FnOnce::call_once(_15, _16) -> [return: bb5, unwind: bb9]; // scope 7 at
只有真正调用,闭包里的drop标记才会起作用。
@biluohc
不过经过你这么一改,加闭包调用和不加闭包调用,可以作为这道题的两种情况去考察了。:D
嗯, , 不过你不用删回复吧, 即使有错误, 以免后来者读不通.
@biluohc 还是删了吧,我怕看的人被我带到歧路里去
https://play.rust-lang.org/?gist=d080a6eb2ce59586b8c03a0c7933e23f&version=nightly
可否得出结论是析构按照comsume顺序?