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 中引用类型的属性和注意点,引用类型包括: 可变字节数组,数组,结构体。1. 可变字节数组string:是一个动态尺寸的utf-8编码字符串,他其实是一个特殊的可变字节数组,同时其 ...