想实现任意链表节点的拼接,用rust会出现运行时错误,而等价的C代码却能得到正确答案,这是为何
struct Node {
elem: usize,
next: Option<Box<Node>>,
}
fn main() {
let mut n1 = Node {
elem: 1,
next: None,
};
let mut n2 = Node {
elem: 2,
next: None,
};
let n3 = Node {
elem: 3,
next: None,
};
n1.next = Some(Box::new(n2));
n2.next = Some(Box::new(n3));
let e = n1.next.unwrap().next.unwrap().elem;
println!("{}", e);
}
编译运行后提示不能对None执行unwrap()
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int elem;
struct Node *next;
} Node_t;
int main() {
Node_t *n1 = malloc(sizeof(Node_t));
n1->elem = 1;
n1->next = NULL;
Node_t *n2 = malloc(sizeof(Node_t));
n2->elem = 2;
n2->next = NULL;
Node_t *n3 = malloc(sizeof(Node_t));
n3->elem = 3;
n3->next = NULL;
n1->next = n2;
n2->next = n3;
printf("%d\n", n1->next->next->elem);
}
编译后运行能输出预期的3
为什么rust会出现这种情况,难道是Box::new(n2)的时候会复制一份n2以至于等后面更新n2之后原来那份保持不变?
1
共 4 条评论, 1 页
评论区
写评论完全不等价啊。Rust 的 node 分配在栈上,C 的在堆里。Rust 处理了内存的释放,C 的没有。
这个时候就该上 unsafe (误
嘛, 一般是用 Option<Rc<RefCell>> (
我用的是 rustc 1.33.0 (2aa4c46cf 2019-02-28) 直接编译没有warning,我觉得很奇怪本来应该报编译时错误的结果给我弄成运行时错误了。
因为编译器没有提示我使用了move的值,所以我一直在想为什么呢为什么呢。。
研究这个问题是因为我想知道有没有某种指针能实现既可以修改对应内存的值,又不占用所有权,现在我们知道n1.next=Box::new(n2)是会拿走n2的所有权的,有没有什么办法能使得n2移走之后还能继续添加元素,达到文中C代码的效果
第一反应: 这代码竟然能编译通过? 然后试了一下: 真能编译通过???
但是编译器是给了 warning 的, LZ 不要忽视啊!!
简要地讲, 在你执行
n1.next = Some(Box::new(n2));
的时候, n2 就已经被 move 掉了, 你后面再对n2.next
赋值已经是未定义行为了, 只不过为了向后兼容这个暂时没有被当做 error.解决方法很简单, 把这两行赋值语句调换一下顺序即可.