rust note 1
从今天起,开始打算写一些博客记录自己在rust学习的过程中的心得。
NOTE1 rust中的as_ref与容器的结合
这个问题来自于rustlings的algorithm的第四题。
考虑这样的一个数据结构
1 | struct TreeNode<T> |
现在已经获取了&TreeNode<T>,应该如何获取左右子结点上的TreeNode借用?
由于self是&TreeNode<T>,所以self.left就是Option<Box<TreeNode<T>>>。注意,当访问借用来的结构体的字段时,并不会得到字段的借用类型,这一点和C语言是一样的,但是由于是访问的借用来的结构体的字段,所以并不能移动这些字段的所有权。所以,这里不可以直接用unwrap()将Option<T>拆开。
那应该怎么写?unwrap()会将其直接拆开,导致所有权move。正确的写法是使用as_ref()(如果是要求mut,就要使用as_mut())把Option<T>转变成Option<&T>,在用unwrap(),这样就只是借用了。
接下来我们得到&Box<TreeNode<T>>,实际上也可以类似的直接用as_ref()得到&TreeNode<T>。这时,&Box<TreeNode<T>>会先自动解引用,再调用as_ref()。
因此,这个问题的最终答案是:
1 | self.left.as_ref().unwrap().as_ref() |
又或者,可以手动执行第二次as_ref的操作(两次解引用:一次auto-deref解&Box,一次解Box本身,然后再来一个引用)得到:
1 | &**(root_node.right.as_ref().unwrap()) |
这个写法更加清晰。
今天就写到这里,事实上虽然同样是调用as_ref(),&Option<T>和&Box<T>似乎有一些区别,主要在于后者会有一次自动解引用再加&,而前者会直接匹配&self。似乎是由值类型和智能指针之间的区别引起的。不过在最终结果看来实际上二者是相同的,等之后读一下源代码再看看具体的实现是不是这样吧。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 鏡ノ家!