rust - 无法理解 &mut &mut 参考
问题描述
我正在关注本教程,但无法理解以下代码:
mail_account.serialize(&mut &mut account.data.borrow_mut()[..])?;
wheremail_account
是一个结构体,.serialize()
是一个派生自Borsh Serialize的方法。
需要注意的另一件事是,它是solana_program 板条箱account
中的AccountInfodata
结构,具有以下类型:Rc<RefCell<&'a mut [u8]>>
作者解释代码如下:
你可能会注意到这个棘手的
&mut &mut account.data.borrow_mut()[..]
表达方式。该serialize()
方法将一个可变切片的引用u8
作为参数,该borrow_mut()
方法返回一个RefMut
. 我们不能传递RefMut
给一个需要切片的方法,所以我们取一个可变切片,RefMut
它返回一个可变切片u8
我所理解的是我们想要将当前mail_account
结构写入account.data
,这就是为什么我们要借用一个可变引用account.data
. 我不明白为什么添加[..]
? 我认为这与serialize()
期待切片有关。
我也很难理解添加&mut &mut
到如何account.data.borrow_mut()[..]
创建一个u8
. 这是如何转换为的u8
?对我来说,它似乎只是为原始引用添加了额外的可变引用。(类型如何从RefMut
变为&[u32]
?)
解决方案
所以,我想,你有多个问题:
-
我不明白为什么添加 [..] 很重要?
-
我也无法理解如何将 &mut &mut 添加到 account.data.borrow_mut()[..] 中创建一个 u8 切片。这是如何转换为u8的?
正如您在问题 1 的答案中看到的那样,这些问题有点交织在一起。
问题 1
当我们查看有关某些索引案例的文档时,我们看到,
account.data.borrow_mut()[..]
是糖
*(account.data.borrow_mut().index_mut(..))
为什么这是一个有效的表达方式?
..
是 的简写RangeFull
。
RangeFull
有一个实现SliceIndex<[u8]>
。
通过这个全面的实现,我们得到一个IndexMut<RangeFull> for [u8]
,它提供
fn index_mut(&mut [u8], index: RangeFull) -> &mut [u8]
现在,其他答案和评论中提到的解除引用强制和/或自动解除引用开始生效。
account.data.borrow_mut().index_mut(..)
并RefMut<&mut [u8]>
实现DerefMut
具有Deref<Target = &mut [u8]>
超级特征的工具。
并以as 超级特征&mut [u8]
实现。DerefMut
Deref<Target = [u8]>
如参考中所述,编译器现在将获取接收器表达式并重复取消引用它,因此它会获得候选类型列表。它还为因取消引用而产生的每种类型添加引用类型和可变引用类型到候选类型列表中。从这个候选类型中,它选择一个提供调用方法的类型。
RefMut<&mut [u8]>
使用account.data.borrow_mut()
&RefMut<&mut [u8]>
&mut RefMut<&mut [u8]>
&mut [u8]
使用*account.data.borrow_mut().deref_mut()
&&mut [u8]
&mut &mut [u8]
[u8]
使用*(*account.data.borrow_mut().deref_mut())
&[u8]
&mut [u8]
(在 7 中,我们正在取消引用指针类型&mut [u8]
,因此不DerefMut
使用 Trait。)
此列表中提供index_mut()
方法的第一个(也是唯一一个)类型是&mut [u8]
,通过IndexMut<FullRange>
实现 for [u8]
,因此&mut [u8]
被选为接收器类型。的返回类型index_mut()
也是&mut [u8]
如此。
所以现在,我们希望能理解,
*(account.data.borrow_mut().index_mut(..))
是[u8]
。
因此:
问题2
&mut &mut account.data.borrow_mut()[..]
有类型&mut &mut [u8]
。
附录
&mut &mut [u8]
需要&mut [u8]
一个Write
实现。
pub fn serialize<W: Write>(&self, writer: &mut W) -> Result<()>
需要一个类型的参数&mut W
,其中W
实现Write
。
W
对类型实现的值的引用Write
需要是可变的,因为我们想要跟踪类型值中的实际写入位置W
。在&mut [u8]
我们简单地改变引用以从底层切片中的不同位置开始的情况下,我们需要对可变引用的可变引用,因为我们想要改变可变引用本身,而不仅仅是底层数据。
附录 2
只需使用
mail_account.serialize(&mut *account.data.borrow_mut())?;
推荐阅读
- python - Python/Pandas:如何选择一个单元格值,给定同一行中的 2 个值?
- r - 使用 for 循环创建数组列表
- c# - 使用 ECDSA x509 证书的 Diffie Hellman 密钥交换
- python - 第 2 行开头的这些单引号有什么作用?
- python - 在python3中实现归并排序
- python-3.x - 将日期列从对象数据类型转换为日期时间数据类型
- postgresql - PostgreSQL 中的短语比较
- c - 连接所有输入字符串 [C 编程]
- docker - 码头工人版本号 18.09
- kubernetes - 如何解析 kubectl describe 输出并获取所需的字段值