Solidity中的数据存储位置

Solidity中的数据存储位置

你会发现这块内容是最具有挑战性的。下面的表格会是每块数据存储位置的概览,标识了读写的权限。具体每个数据存储位置的详情,可以阅读对应的具体模块。

数据读写权限

我们什么时候使用关键字, storage、memory、calldata ?

任何具有复杂类型的变量比如array,struct,mappings或者enum必须指定一个数据存储位置。

Storage

Storage对应合约内的存储。

你可以把你不想被cloned的变量作为Storage存储。

Storage是长期有效的,但是成本比较高。

Memory

在ETH中memory保存了临时变量,就像函数的参数。

而且,memory变量在外部函数调用时会被清除。

Memory是短暂其便宜的!

Calldata

calldata几乎是免费的,但是有一个长度的限制。

Stack

stack存储了小的局部变量。然而它只能存储数量有限的变量。stack在eth中只能有最大1024个元素。

一旦函数执行完成就结束。

函数参数的数据存储位置规则

下面的表格展示了函数参数可选的数据类型,取决于函数的可见性。

外部函数或者公有函数不能访问storage

函数内部的数据存储位置

在函数内部所有的三种数据存储位置都能被指定,不管函数的可见性。然后在在赋值的时候存在一些具体的规则,如下面表格中展示:

Storage

storage references can be assigned a:
state variable directly
state variable via storage reference
memory reference
calldata value directly
calldata value via calldata reference

Memory

memory references can be assigned a:
state variable directly
state variable via storage reference
memoryreference
calldata value directly
calldata value via calldata reference

Calldata

calldata references can be assigned a:
state variable directly
state variable via storagereference
memoryreference
calldata value directly
calldata value via calldatareference

数据存储位置-行为

当我们指定数据存储位置的时候,有2件主要的事情需要考虑:影响范围和gas的使用量。

让我们用一个简单的合约来更好的了解这个区别。为什么比较不用的存储位置,我们使用了不同的函数使用不同的数据类型关键词。

  • a getter storage
  • a getter memory
  • a setter storage
  • a setter memory
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

contract Garage {
    struct Item {
        uint256 units;
    }
    mapping(uint256 => Item) items;

    // gas (view) 24025
    function getItemUnitsStorage(uint _itemIndex) public view returns(uint) {
        Item storage item = items[_itemIndex];
        return item.units;
    }

    // gas (view) 24055
    function getItemUnitsMemory(uint _itemIndex) public view returns (uint) {
        Item memory item = items[_itemIndex];
        return item.units;
    }
}

## github仓库 
<https://github.com/coffiasd/solidity-learn>

猜你喜欢

转载自blog.csdn.net/coffiasd/article/details/126513337