27存储位置
data location
- storage:状态变量
- memory:局部变量
- calldata:和memory类似,但是只能用在函数输入的参数中
storage vs memory¶
storage从链上中读取数据并且修改
memory只能从链上读取数据,无法修改链上数据
// SPDX-License-Identifier: MIT
pragma solidity 0.8.18;
contract DataLocations{
struct MyStruct{
uint foo;
string text;
}
mapping (address=>MyStruct) public myStructs;
function examples() external {
myStructs[msg.sender]=MyStruct({
foo:123,
text:"bar"
});
// storage和memory区别
// storage从链上中读取数据并且修改
MyStruct storage mySturct=myStructs[msg.sender];
mySturct.text="foo";
// memory只能从链上读取数据,无法修改链上数据
// 本次修改只在该函数内有效,对链上数据无影响
MyStruct memory readOnly=myStructs[msg.sender];
readOnly.foo=346;
}
}
数组和string
内存的数据必须是定长。
动态数组只能用在状态变量和局部变量。
// 数组array要标明存储位置,string也是一个特殊的数组
function examples3(uint[]memory y, string memory s) external returns (uint[] memory){
myStructs[msg.sender]=MyStruct({
foo:123,
text:"bar"
});
MyStruct storage mySturct=myStructs[msg.sender];
mySturct.text="foo";
MyStruct memory readOnly=myStructs[msg.sender];
readOnly.foo=346;
//定义数组
uint [] memory memArr=new uint[](3);
memArr[0]=234;
return memArr;
}
callable和memory
这种情况,调用_internal(params),calldata标注的话是直接传参进来
// 数组array要标明存储位置,string也是一个特殊的数组
function examples3(uint[]calldata y, string calldata s) external returns (uint[] memory){
myStructs[msg.sender]=MyStruct({
foo:123,
text:"bar"
});
MyStruct storage mySturct=myStructs[msg.sender];
mySturct.text="foo";
MyStruct memory readOnly=myStructs[msg.sender];
readOnly.foo=346;
_internal(y);
//定义数组
uint [] memory memArr=new uint[](3);
memArr[0]=234;
return memArr;
}
function _internal(uint[] calldata y) private {
uint x=y[0];
}
如果是memory
会先拷贝一份所有的内容,很浪费gas(很多时候只需要单个参数)