Solidity中的引用类型
引用类型(Reference Type)包含:数组(array)、结构体(struct)、映射(mapping),这种类型变量占用空间较大,赋值时直接传递地址(类似C语言的指针)。由于该类型比较复杂,因此我们使用时必须声明数据存储的位置。
数据的位置
Solidity的数据存储位置有三类:storage、memory、calldata。不同的存储位置的gas fee不同。
storage:合约的状态变量一般都默认是storage,存储在链上,类似存储在计算机的硬盘,因此消耗gas fee较高。
memory:函数里的参数和临时变量一般使用memory,存储在内存,不上链。
calldata:与memory类似,不同点是calldata声明的变量不能进行修改,一般用于函数的参数。
数据位置和赋值规则
在不同的存储类型相互赋值时,有时会产生独立的的副本(修改新变量不会影响原变量),有时会产生引用(修改新变量影响原变量)。规则如下:
1、sotrage(合约的状态变量)赋值给本地storage(函数里)的时候,会创建引用,即修改新变量影响原变量。如图所示。
2、storage赋值给memory,会创建独立副本,不会影响原变量。反之也是如此。如图所示。
3、memory给memory创建变量,会创建引用。
4、其它情况,变量赋值给storage,都会创建独立的副本,不会影响原变量。
变量的作用域
Solidity中有三种作用域,分别是状态变量(state variable)、局部变量(local variable)、全局变量(global variable)。
1、状态变量,是存储在链上的变量,所有合约内的函数都可以访问,gas fee消耗较高,状态变量在合约内、函数外声明:
2、局部变量,是仅在函数内部执行过程有效,函数退出后,变量无效。局部变量存储在内存,不上链,gas fee消耗低,局部变量在函数内部声明:
3、全局变量,是全局工作范围内的变量,基本都是Solidity的预留关键字,可以不需要在函数内声明就直接使用:
tips:图中使用了msg.sender,gasleft,msg.data,分别代表了发起地址,剩余gas fee,请求数据。下面展示常用的全局变量图:(取自github)
总结
这一篇文章,我们讲了Solidity中的引用类型、数据位置、变量的作用域。重点是了解storage、memory、calldata三个关键字的用法,因为其作用是节省空间和降低gas fee,因此需要认真了解学习。