一丶memory:

内存memory,用于暂存数据。其中存储的内容会在函数被调用(包括外部函数)时擦除,所以其使用开销相对较小。

二丶storage:

存储storage,贮存了合约声明中所有的变量。 虚拟机会为每份合约分别划出一片独立的 存储storage 区域,并在函数相互调用时持久存在,所以其使用开销非常大。

三丶stack:

栈stack,用于存放小型的局部变量。使用几乎是免费的,但容量有限。

四丶存储区域:

不同数据类型的变量会有各自默认的存储地点:

状态变量总是会贮存在 存储storage
函数参数默认存放在 内存memory
结构、数组或映射类型的局部变量默认会放在 存储storage
除结构、数组及映射类型之外的局部变量,会储存在

五丶注意事项:

一个常见误区就是声明了一个局部变量,就认为它会创建在 内存memory 中,其实它会被创建在 存储storage 中:

/// 这份合约包含一处错误

pragma solidity ^0.4.0;

contract C {
    uint someVariable;
    uint[] data;

    function f() public {
        uint[] x;
        x.push(2);
        data = x;
    }
}

局部变量 x 的数据类型是 uint[] storage,但由于 存储storage 不是动态分配的,它需要在使用前通过状态变量赋值。所以 x 本身不会被分配 存储storage 的空间,取而代之的是,它只是作为 存储storage 中已有变量的别名。
实际上会发生的是,编译器将 x 解析为一个 存储storage 指针,并默认将指针指向 存储插槽storage slot 0 。这就造成 someVariable (贮存在 存储插槽storage slot 0)会被 x.push(2) 更改。

注:在本例中,两个合约变量 someVariable 和 data 会被预先分配到两个 存储插槽storage slot 中,即 存储插槽storage slot 0 和 存储插槽storage slot 1 。上面的程序会使局部变量 x 变成指向保存了变量 someVariable 的 存储插槽storage slot 0 的指针。

/// 正确的做法
pragma solidity ^0.4.0;

contract C {
    uint someVariable;
    uint[] data;

    function f() public {
        uint[] x = data;
        x.push(2);
    }
}

四丶上一篇:solidity笔记(6)——modifier用法

solidity笔记(6)——modifier用法

五丶下一篇:solidity笔记(8)——pure用法

solidity笔记(8)——pure用法

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐