关于mapping
mapping是一个有点特殊性的数据类型,比如
它不能遍历
不能出现在合约公有函数的参数和返回值中
事实上它也不能进行值拷贝,比如将一个mapping类型的成员变量赋值给另一个mapping类型的成员变量
以上三个特质并不是平行关系,不能遍历是更根本的属性,因为不能遍历,所以无法拷贝,因为拷贝就是一种搬运过程,搬运总要先能把东西找全。传参或返回值也一样,也是数据的搬运。
没有遍历能力的技术原因在于mapping在storage中的存储方式。当根据key去取一个value时,是根据这个mapping的slot位置下标和key值按照某种算法算出value在storage中的位置,取到它。对于任何key都能够算出一个位置取到一个value,哪怕这个key从来没有被存过。这意味着任何mapping成员变量的大小都是2的256次方,显然是无法遍历的。
说无法遍历是计算的逻辑,因为2的256次方的计算复杂度不具可行性,但是纯粹的逻辑上,mapping有大小,也能遍历。只是大到难以想象。
mapping在library的public函数中可以出现,这是因为这时这个public函数是delagatecall调用,本质上是库函数调用者合约的内部调用,自然可以进行引用传递,不会触发值拷贝。
这些问题的来龙去脉,一般教程和官方文档也是不作梳理,只是罗列,这里记一下。