说明:
引用类型的数据进行复制移动等 *** 作时需要消耗大量Gas,非常昂贵,所以使用它们时,必须考虑存储位置。例如,是保存在内存中,还是保存在EVM存储区中。
数据位置
storagememorycalldatastack名称 | 值 |
---|---|
storage | 该存储位置存储永久数据,这意味着该数据可以被合约中的所有函数访问。可以把它视为计算机的硬盘数据,所有数据都永久存储。保存在存储区(storage)中的变量,以智能合约的状态存储,并且在函数调用之间保持持久性。与其他数据位置相比,存储区数据位置的成本较高。 |
memory | 内存位置是临时数据,比存储位置便宜。它只能在函数中访问。通常,内存数据用于保存临时变量,以便在函数执行期间进行计算。一旦函数执行完毕,它的内容就会被丢弃。你可以把它想象成每个单独函数的内存(RAM)。 |
calldata | calldata是不可修改的非持久性数据位置,所有传递给函数的值,都存储在这里。此外,calldata是外部函数的参数(而不是返回参数)的默认位置。 |
stack | 堆栈是由EVM (Ethereum虚拟机)维护的非持久性数据。EVM使用堆栈数据位置在执行期间加载变量。堆栈位置最多有1024个级别的限制。可以看到,要永久性存储,可以保存在存储区(storage)。 |
1 状态变量总是存储在存储区中。
// SPDX-License-Identifier: SimPL-3.0
pragma solidity ^0.7.0;
contract DataLocation {
// storage
uint stateVariable;
uint[] stateArray;
}
此外,不能显式地标记状态变量的位置。
// SPDX-License-Identifier: SimPL-3.0
pragma solidity ^0.7.0;
contract DataLocation {
uint storage stateVariable; // 错误
uint[] memory stateArray; // 错误
} ```
2 函数参数包括返回参数都存储在内存中。
```javascript
// SPDX-License-Identifier: SimPL-3.0
pragma solidity ^0.7.0;
contract DataLocation {
// storage
uint stateVariable;
uint[] stateArray;
function calculate(uint num1, uint num2) public pure returns (uint result) {
return num1 + num2;
}
}
// 此处,函数参数 uint num1 与 uint num2,返回值 uint result 都存储在内存中。
2 值类型的局部变量存储在内存中。但是,对于引用类型,需要显式地指定数据位置。
// SPDX-License-Identifier: SimPL-3.0
pragma solidity ^0.7.0;
contract Locations {
/* 此处都是状态变量 */
// 存储在storage中
bool flag;
uint number;
address account;
function doSomething() public pure {
/* 此处都是局部变量 */
// 值类型
// 所以它们被存储在内存中
bool flag2;
uint number2;
address account2;
// 引用类型,需要显示指定数据位置,此处指定为内存
uint[] memory localArray;
}
}
不能显式覆盖具有值类型的局部变量。
// SPDX-License-Identifier: SimPL-3.0
pragma solidity ^0.7.0;
function doSomething() public {
/* 此处都是局部变量 */
// 值类型
bool memory flag2; // 错误
uint Storage number2; // 错误
address account2;
}
3 外部函数的参数(不包括返回参数)存储在 calldata中。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)