在Solidity中,有一些数据类型是引用类型,如:
数组(string和bytes是特殊的数组,也是引用类型)结构体(struct)映射(mapping)在Solidity中使用引用类型的时候,必须指定数据的位置。
存储位置在合约中声明的变量都有一个存储位置,用于指明变量的值存储在哪里。
Solidity提供了三种类型的存储位置:
storagememorycalldata storage链上存储空间。该存储位置用于存储永久数据,只要合约存在数据就一直有效。存储的 Gas 较高。
其中:
状态变量的存储方式强制是storage
;局部变量的存储方式可以声明成 storage
、memory
或 calldata
;映射(mapping)只能存储在 storage
中。
memory
内存存储。即数据存储在内存中,数据只在其生命周期内(函数调用期间)有效。
calldata调用数据。一个特殊的只读数据位置,用来存储函数调用的参数(包括内部和外部函数),类似于 memory
。使用 calldata
变量的好处是,它不用将数据的副本保存到内存中,并确保不会修改数据。
总结:
状态变量的存储方式都是storage
;局部变量的存储方式可以声明成 storage
、memory
或 calldata
;公用函数(public)和外部函数(external)中,函数参数的存储方式只能是 memory
或 calldata
;私有函数(private)和内部函数(internal)中,函数参数的存储方式还可以是 storage
;映射(mapping)只能存储在 storage
中,且不能在函数内部定义,映射一般声明为状态变量;一般建议将函数参数和局部变量的存储方式声明为 memory
。
合约例子
下面是一个合约例子,用来演示数据存储位置的用法。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
// 变量存储位置和作用域
contract DataStorages {
// 状态变量强制为 storage
string public str;
bytes public bs;
uint[] public arr;
mapping(address => uint) map;
struct Student {
string name;
uint score;
}
Student[] public students;
// 公共函数(public)和外部函数(external)中,存储位置可以声明成 meomory 和 calldata
// 私有函数(private)和内部函数(internal)中,存储位置还可以声明成 storage
// 字符串的存储位置
function setString(string memory _str) public {
str = _str;
}
// 字节的存储位置
function setBytes(bytes memory _bs) public {
bs = _bs;
}
// 数组的存储位置
function setArray(uint[] memory _arr) public {
for(uint i = 0; i < _arr.length; i++) {
arr.push(_arr[i]);
}
}
// 结构体的存储位置
function setStruct(Student calldata _student) public {
students.push(_student);
}
// 在内部函数(internal)中,变量可以声明成 storage
function getLength(uint[] storage _arr) internal view returns(uint) {
return(_arr.length);
}
// 调用内部函数
function test() public view returns(uint) {
return getLength(arr);
}
}
**输出:**我们在Remix中编译、部署和运行这个合约例子,执行结果如下图:
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)