gpt4 book ai didi

rust - 我们是否需要为链表手动创建析构函数?

转载 作者:行者123 更新时间:2023-11-29 08:10:12 26 4
gpt4 key购买 nike

我正在阅读 Learning Rust With Entirely Too Many Linked Lists我很困惑为什么链表(堆栈)needs a destructor .

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

我对有和没有手动析构函数的版本进行了基准测试,我发现“没有析构函数”的版本有更好的性能:

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

最佳答案

你是对的。该列表将自行清理。正如作者所说:

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

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

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

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

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

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

#[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)

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

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

看完文章,解释的比我的好。

关于rust - 我们是否需要为链表手动创建析构函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38147453/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com