Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Advance] 闭包捕获变量顺序 #6

Open
ZhangHanDong opened this issue Nov 18, 2017 · 20 comments
Open

[Advance] 闭包捕获变量顺序 #6

ZhangHanDong opened this issue Nov 18, 2017 · 20 comments

Comments

@ZhangHanDong
Copy link
Contributor

ZhangHanDong commented Nov 18, 2017

let c = move || {
        {
            let y_ref = &y;
        }
        x; y; z;
    };

假如x、y、z都是外部变量,那么上面闭包示例中,是先捕获y呢,还是先捕获z ?析构顺序是什么样的?

@ZhangHanDong ZhangHanDong changed the title [Questions] 闭包捕获变量顺序 [Advance] 闭包捕获变量顺序 Nov 18, 2017
@biluohc
Copy link

biluohc commented Nov 24, 2017

这个是按栈的顺序吗?
即 z,y,x -> x,y,z

@iovxw
Copy link

iovxw commented Nov 24, 2017

捕获顺序为 y, x, z, 单纯是按闭包内使用的顺序

析构为 x, y, z, 因为第五行 consume 的顺序是这样的

@ZhangHanDong
Copy link
Contributor Author

@iovxw 析构也是y,x,z

@ZhangHanDong
Copy link
Contributor Author

@biluohc 你说的是let声明绑定的析构顺序,这里是闭包,略有不同

@ZhangHanDong
Copy link
Contributor Author

看来每个issue需要配上play比较好

@biluohc
Copy link

biluohc commented Nov 25, 2017

总感觉莫名其妙,可以写个结构加闭包验证下

@ZhangHanDong
Copy link
Contributor Author

@biluohc
Copy link

biluohc commented Nov 25, 2017

@biluohc
Copy link

biluohc commented Nov 25, 2017

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: ();

@biluohc
Copy link

biluohc commented Nov 25, 2017

@iovxw 谢啦.

@ZhangHanDong
Copy link
Contributor Author

@biluohc y,x,z那是捕获顺序。
你这个例子,调用了闭包,是另外一道题了。

@biluohc
Copy link

biluohc commented Nov 25, 2017

那你说说闭包使用与否对析构有什么影响?
因为没有闭包内部的作用域使用, 就按catch顺序drop?

@ZhangHanDong
Copy link
Contributor Author

@biluohc 闭包调用确实是有影响的。目前按结果来看是这样。

@biluohc
Copy link

biluohc commented Nov 25, 2017

我去, 还能像css盒子模型那样重合..

闭包调用换成; 就和那个没有使用闭包的一样了.
所以你说的这个坑和这个题没有关系吧.

@ZhangHanDong
Copy link
Contributor Author

@biluohc 汗! 那个说法错了,我改了。
不是那个坑的问题。

@ZhangHanDong
Copy link
Contributor Author

@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标记才会起作用。

@ZhangHanDong
Copy link
Contributor Author

@biluohc

不过经过你这么一改,加闭包调用和不加闭包调用,可以作为这道题的两种情况去考察了。:D

@biluohc
Copy link

biluohc commented Nov 25, 2017

嗯, , 不过你不用删回复吧, 即使有错误, 以免后来者读不通.

@ZhangHanDong
Copy link
Contributor Author

@biluohc
还是删了吧,我怕看的人被我带到歧路里去

@huangjj27
Copy link

https://play.rust-lang.org/?gist=d080a6eb2ce59586b8c03a0c7933e23f&version=nightly

可否得出结论是析构按照comsume顺序?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants