Solidity 存储位置 memory,storage,calldata

引用类型在 Solidity 中数据有一个额外的属性:存储位置,可选项为 memory 和 storage。

  • memory:存储在内存中,即分配、即使用,越过作用域则不可访问,等待被回收。
  • storage:永久存储在以太坊区块链中,更具体地说存储在存储 Merkle Patricia 树中,形成帐户状态信息的一部分。一旦使用这个类型,数据将永远存在。
  • calldata:存储函数参数,它是只读的,不会永久存储的一个数据位置。外部函数的参数被强制指定为 calldata,效果与 memory 类似。

1. 强制的数据位置

外部函数 (external function) 的参数强制为:calldata。

状态变量强制为: storage。

pragma solidity ^0.8.0;
contract StateVariable{
    struct S{        string a;        uint b;    }
    //状态变量,默认是 storage
    S s;
}

2. 默认数据位置

函数参数,返回参数:memory。

局部变量:storage。

pragma solidity ^0.8.0;
contract SimpleAssign{     struct S{        string a;        uint b;    }    function assign(S s) internal{         // 函数参数默认是 memory 类型,即 s 是 memory 类型
        // 局部变量默认 storage 类型
        // S tmp = s; 报错
  }
}

这里将一个memory类型的参数赋值给storage类型的局部变量会报错。

3. 转换问题

3.1 storage–>storage

把一个storage类型赋值给一个 storage 类型时,只是修改其指针(引用传递)。

pragma solidity ^0.8.0;
contract StorageToStorageTest{
    struct S{string a;uint b;}
    //默认是storage的
    S s;
    function storageTest(S storage s) internal{
        S test = s;
        test.a = "Test";
    }
    function call() returns (string){
        storageTest(s);
        return s.a; //Test
    }}

3.2 memory–>storage

分为 2 种情况:

a. 将 memory–>状态变量; 即将内存中的变量拷贝到存储中(值传递)

pragma solidity ^0.8.0;
contract StorageToStorageTest{
    struct S{string a;uint b;}
    //默认是storage
    S s;
    function storageTest(S s) internal{
        s = s; 
        s.a = "Test";
    }
    function call() returns (string){
        storageTest(s);
        return s.a;
    }
}

  b.将memeory–>局部变量 报错

3.storage–>memory:即将数据从storage拷贝到memory中

  pragma solidity ^0.4.0;
  contract StorageToMemory{
      struct S{string a;uint b;}
      S s = S("storage", 1);
  function storageToMemory(S storage x) internal{
     S memory tmp = x;//由Storage拷贝到memory中
     //memory的修改不影响storage
     tmp.a = "Test";
  }

  function call() returns (string){
    storageToMemory(s);
    return s.a;//storage
  }
}

4.memory–>memory 和storage转storage一样是引用传递

  pragma solidity ^0.4.0;
  contract MemoryToMemory{
      struct S{string a;uint b;}  
      function smemoryTest(S s) internal{
            S memory test = s;
            test.a = "Test";
      }
      function call() returns (string){
           //默认是storage的
            S memory s = S("memory",10);
            smemoryTest(s);
            return s.a;//Test
       }
  }

下一章:Solidity 引用类型

本章节主要介绍 solidity 中引用类型的属性和注意点,引用类型包括: 可变字节数组,数组,结构体。1. 可变字节数组string:是一个动态尺寸的utf-8编码字符串,他其实是一个特殊的可变字节数组,同时其 ...