我们是否需要手动为链表创建析构函数? [英] Do we need to manually create a destructor for a linked list?

查看:40
本文介绍了我们是否需要手动为链表创建析构函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在阅读 学习 Rust链表太多,我很困惑为什么链表(堆栈)需要一个析构函数.

我认为当列表值超出范围时,列表本身和所有节点都会被清理.只是为了演示吗?

I think when the list value is out of the scope, the list itself, and all nodes would be clean up. Is it just for demonstration?

我对使用和不使用手动析构函数的版本进行了基准测试,我发现不使用析构函数"一个性能更好:

I benchmarked the version with and without a manual destructor and I found the "without destructor" one has better performance:

for _ in 1..30000000 {
    let mut list = List::new();
    list.push(1);
    assert_eq!(list.pop(), Some(1));
}

使用手动析构函数:

real    0m11.216s
user    0m11.192s
sys     0m 0.020s

没有手动析构函数:

real    0m9.071s
user    0m9.044s
sys     0m0.004s

推荐答案

你说得对.该列表将自行清理.正如作者所说:

You are correct. The list would clean itself up. As the author stated:

所有这些都由我们自动处理......一举两得.

All that's handled for us automatically... with one hitch.

然后他们解释了为什么自动处理不好:自动销毁过程为列表的头部调用drop,然后为第一个元素调用drop.等等等等.

They then explain why the automatic handling is bad: The automatic destruction process calls drop for the head of the list, which in turn calls drop for the first element. And so on and so on.

这是一个调用函数的函数(有无限可能的重复),它迟早会炸毁你的堆栈.

This is a function calling a function calling a function (with infinite possible repetitions) which will blow up your stack sooner or later.

这个测试会导致这样的堆栈溢出:

This test causes such a stack overflow:

#[test]
fn build_really_big_stack() {
    let mut stack = List::new();
    for i in 0..1_000_000 {
        stack.push(i);
    }
}

如果您使用 --release 为两个版本构建,则表明它们的性能几乎相同:

If you build with --release for both versions, it shows that they perform nearly equally:

#[bench]
fn bench_auto_destructor(b: &mut Bencher) {
    b.iter(|| {
        let mut list = List::new();
        for i in 0..1000 {
            list.push(i);
        }
        assert_eq!(list.pop(), Some(999));
    });
}

#[bench]
fn bench_man_destructor(b: &mut Bencher) {
    b.iter(|| {
        let mut list = ManualDestructorList::new();
        for i in 0..1000 {
            list.push(i);
        }
        assert_eq!(list.pop(), Some(999));
    });
}

test bench_auto_destructor ... bench:      81,296 ns/iter (+/- 302)
test bench_man_destructor  ... bench:      85,756 ns/iter (+/- 164)

只有一个元素,就像在您的基准测试中一样:

With only one element, like in your benchmarks:

test bench_auto_destructor ... bench:          69 ns/iter (+/- 1)
test bench_man_destructor  ... bench:          67 ns/iter (+/- 2)

把文章读到最后,它的解释比我的好.

Read the article to the end, its explanation is better than mine.

这篇关于我们是否需要手动为链表创建析构函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆