14.DataLocations
Variables are declared as either storage
, memory
or calldata
to explicitly specify the location of the data.
storage - variable is a state variable (store on blockchain) 永久存储在区块链中的变量
memory - variable is in memory and it exists while a function is being called 变量则是临时的,当外部函数对某合约调用完成时,内存型变量即被移除。
calldata - special data location that contains function arguments
补充:
内存(memory)位置还包含2种类型的存储数据位置,一种是calldata,一种是栈(stack)。 calldata:这是一块只读的,且不会永久存储的位置,用来存储函数参数。
外部函数的参数(非返回参数)的数据位置被强制指定为 calldata ,效果跟 memory 差不多。
栈(stack):另外,EVM是一个基于栈的语言,栈实际是在内存(memory)的一个数据结构,每个栈元素占为256位,栈最大长度为1024。
值类型的局部变量是存储在栈上。
storage: modify data
memory: read data
pragma solidity ^0.8.1;
contract DataLocation {
struct MyStruct{
uint foo;
string text;
}
mapping (address=>MyStruct) public myStructs;
function examples() external {
myStructs[msg.sender]=MyStruct({
foo:123,
text:"bar"
});
MyStruct storage myStruct=myStructs[msg.sender];
myStruct.text="foo";
MyStruct memory readOnly=myStructs[msg.sender];
readOnly.foo=456;
}
}
storage的数值可以改
memory标记的,这个方法结束后,修改会被抹去
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.1;
contract SimpleStorage {
string public text;
function set(string calldata _text) external {
text=_text;
}
function get() external view returns (string memory){
return text;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract DataLocations {
uint[] public arr;
mapping(uint => address) map;
struct MyStruct {
uint foo;
}
mapping(uint => MyStruct) myStructs;
function f() public {
// call _f with state variables
_f(arr, map, myStructs[1]);
// get a struct from a mapping
MyStruct storage myStruct = myStructs[1];
// create a struct in memory
MyStruct memory myMemStruct = MyStruct(0);
}
function _f(
uint[] storage _arr,
mapping(uint => address) storage _map,
MyStruct storage _myStruct
) internal {
// do something with storage variables
}
// You can return memory variables
function g(uint[] memory _arr) public returns (uint[] memory) {
// do something with memory array
}
function h(uint[] calldata _arr) external {
// do something with calldata array
}
}