【区块链笔记】ETH_Solidity数据位置(07)

Page content

这篇文章简单的整理了Solidity数据位置

1.Solidity数据位置

所有的复杂类型,即数组、结构和映射类型,都有一个额外属性,“数据位置”,用来说明数据是保存在内存memory中还是存储storage中

  • 根据上下文不同,大多数时候数据有默认的位置,但也可以通过在类型名后增加关键字 storage 或 memory 进行修改
  • 函数参数(包括返回的参数)的数据位置默认是memory,局部变量的数据位置默认是 storage,状态变量的数据位置强制是 storage
  • 另外还存在第三种数据位置,calldata,这是一块只读的,且不会永久存储的位置,用来存储函数参数。
    外部函数的参数(非返回参数) 的数据位置被强制指定为calldata ,效果跟 memory 差不多

2.数据位置整理

强制指定的数据位置

  • 外部函数的参数(不包括返回参数):calldata;
  • 状态变量:storage

默认数据位置

  • 函数参数(包括返回参数):memory;
  • 引用类型的局部变量:storage
  • 值类型的局部变量:栈(stack)

特别要求

公开可见(publiclyvisible)的函数参数一定是memory类型,
如果要求是 storage 类型 则必须是 private 或者 internal 函数,这是为了 防止随意的公开调用占用资源

3.注意事项(例子)

例子1

pragma solidity >=0.4.0 <0.5.0;
contract C {
    uint public a;
    uint public b;
    uint[] public data;
    function fn() public {
        uint[] x;
        x.push(2);
        data = x;
    }
}

这里每次调用fn的方法的时候a值会自动+1;
因为在函数里声明局部变量storage引用类型,赋初始值的话,他会默认指向第一个值。
uint[] x => a ;
而且每次调用的时候x的length会赋给a,所以每次push一次会自动+1;

修改后 ==>

pragma solidity >=0.4.0 <0.5.0;
contract C {
    uint public a;
    uint public b;
    uint[] public data;
    function fn() public {
        uint[] x = data;
        x.push(2);
    }
}

例子2

pragma solidity ^0.4.0; 
    contract C {
    uint[] x;
    function f(uint[] memoryArray) public {
        x = memoryArray; 
        uint[] y = x;
        y[7];
        y.length = 2; 
        delete x;
        y = memoryArray; // 这里会报错,因为memoryArray是引用值,不能直接赋给storage类型的引用值。 值的话可以直接拷贝
        delete y;
        g(x);
        h(x);
    }
    function g(uint[] storage storageArray) internal {} 
    function h(uint[] memoryArray) public {} 
}

欢迎大家的意见和交流

email: li_mingxie@163.com