Rust 创建链表时出现意外堆栈溢出
我一直试图通过扩展 我已经编写了一个构造函数,将泛型向量转换为链表,但是如果向量足够大,使用它会导致堆栈溢出。这让我感到困惑,因为我认为链表是在堆上创建的,因为列表中的每个元素都有一个包含下一个元素的自有框 Rust是我在担心内存管理时使用的第一种语言,所以我有点迷路了。如能解释,将不胜感激。谢谢 我的代码仅被截断为相关gubbins:Rust 创建链表时出现意外堆栈溢出,rust,Rust,我一直试图通过扩展 我已经编写了一个构造函数,将泛型向量转换为链表,但是如果向量足够大,使用它会导致堆栈溢出。这让我感到困惑,因为我认为链表是在堆上创建的,因为列表中的每个元素都有一个包含下一个元素的自有框 Rust是我在担心内存管理时使用的第一种语言,所以我有点迷路了。如能解释,将不胜感激。谢谢 我的代码仅被截断为相关gubbins: use std::mem::swap; enum ListItem<T> { Node(T, Box<ListItem<T&
use std::mem::swap;
enum ListItem<T> {
Node(T, Box<ListItem<T>>),
Cap
}
impl <T> ListItem<T> {
fn append(&mut self, x: T) {
match *self {
Node(_, ref mut a@box Cap) => *a = box Node(x, box Cap),
Node(_, ref mut a@box Node(_, _)) => a.append(x),
Cap => {
let mut n = Node(x, box Cap);
swap(&mut n, self);
}
};
}
}
impl <T: Clone> ListItem<T> {
fn new_from_vec(x: &mut Vec<T>) -> ListItem<T>{
let mut l = Cap;
for v in x.iter() {
l.append((*v).clone());
}
return l;
}
}
fn main() {
let mut v: Vec<int> = vec![];
for n in range(1i, 500001) {
v.push(n);
}
println!("Done creating vector.");
let x = ListItem::new_from_vec(&mut v);
println!("Done creating linked list.");
}
使用std::mem::swap;
枚举列表项{
节点(T,盒),
帽子
}
impl列表项{
fn追加(&mut self,x:T){
匹配自我{
节点(u,ref muta@boxCap)=>*a=箱节点(x,箱盖),
节点(u,ref muta@box节点(,))=>a.append(x),
上限=>{
设mut n=节点(x,箱盖);
交换(&M)n,自交换;
}
};
}
}
impl列表项{
fn新的\u来自\u vec(x:&mut vec)->ListItem{
设mut l=Cap;
对于x.iter()中的v{
l、 追加(*v.clone());
}
返回l;
}
}
fn main(){
让mut v:Vec=Vec![];
适用于范围内的n(1i,500001){
v、 推(n);
}
println!(“创建向量完成”);
设x=ListItem::new_from_vec(&mut v);
println!(“创建链接列表完成”);
}
它打印
Done creating vector.
,然后打印task''在进入下一个println之前溢出了堆栈代码>堆栈溢出通常是递归深入的标志。如果仔细查看代码,您可能会发现递归:
impl <T> ListItem<T> {
fn append(&mut self, x: T) {
match *self {
Node(_, ref mut a@box Cap) => *a = box Node(x, box Cap),
Node(_, ref mut a@box Node(_, _)) => a.append(x), // <---
Cap => {
let mut n = Node(x, box Cap);
swap(&mut n, self);
}
};
}
}
impl列表项{
fn追加(&mut self,x:T){
匹配自我{
节点(u,ref muta@boxCap)=>*a=箱节点(x,箱盖),
节点(u,ref muta@box节点(,))=>a.append(x),//{
设mut n=节点(x,箱盖);
交换(&M)n,自交换;
}
};
}
}
这意味着,对于列表中已经存在的每个元素,您将在堆栈上创建一个新的函数框架(除非编译器对其进行优化),对于足够数量的元素,该框架将决定性地溢出堆栈
为了避免溢出,您可以切换到迭代版本(使用循环)。堆栈溢出通常是递归深入的标志。如果仔细查看代码,您可能会发现递归:
impl <T> ListItem<T> {
fn append(&mut self, x: T) {
match *self {
Node(_, ref mut a@box Cap) => *a = box Node(x, box Cap),
Node(_, ref mut a@box Node(_, _)) => a.append(x), // <---
Cap => {
let mut n = Node(x, box Cap);
swap(&mut n, self);
}
};
}
}
impl列表项{
fn追加(&mut self,x:T){
匹配自我{
节点(u,ref muta@boxCap)=>*a=箱节点(x,箱盖),
节点(u,ref muta@box节点(,))=>a.append(x),//{
设mut n=节点(x,箱盖);
交换(&M)n,自交换;
}
};
}
}
这意味着,对于列表中已经存在的每个元素,您将在堆栈上创建一个新的函数框架(除非编译器对其进行优化),对于足够数量的元素,该框架将决定性地溢出堆栈
为了避免溢出,您可以切换到迭代版本(带有循环)。不幸的是,Rust不能做到这一点,这意味着您不能依赖递归进行迭代繁重的操作
据报道,他们似乎不太可能在未来增加这一功能
恐怕您必须将代码转换为常规循环。不幸的是,Rust不能做到这一点,这意味着您不能依赖递归进行迭代繁重的操作
据报道,他们似乎不太可能在未来增加这一功能
恐怕您必须将代码转换为常规循环