数据位置(Data location)

复杂类型,如数组(arrays)数据结构(struct)在Solidity中有一个额外的属性,数据的存储位置。可选为memorystorage

memory存储位置同我们普通程序的内存一致。即分配,即使用,越过作用域即不可被访问,等待被回收。而在区块链上,由于底层实现了图灵完备,故而会有非常多的状态需要永久记录下来。比如,参与众筹的所有参与者。那么我们就要使用storage这种类型了,一旦使用这个类型,数据将永远存在。

基于程序的上下文,大多数时候这样的选择是默认的,我们可以通过指定关键字storagememory修改它。

默认的函数参数,包括返回的参数,他们是memory。默认的局部变量是storage1。而默认的状态变量(合约声明的公有变量)是storage

另外还有第三个存储位置calldata。它存储的是函数参数,是只读的,不会永久存储的一个数据位置。外部函数的参数(不包括返回参数)被强制指定为calldata。效果与memory差不多。

数据位置指定非常重要,因为不同数据位置变量赋值产生的结果也不同。在memorystorage之间,以及它们和状态变量(即便从另一个状态变量)中相互赋值,总是会创建一个完全不相关的拷贝。

将一个storage的状态变量,赋值给一个storage的局部变量,是通过引用传递。所以对于局部变量的修改,同时修改关联的状态变量。但另一方面,将一个memory的引用类型赋值给另一个memory的引用,不会创建另一个拷贝。

pragma solidity ^0.4.0;

contract DataLocation{
  uint valueType;
  mapping(uint => uint) public refrenceType;

  function changeMemory(){
    var tmp = valueType;
    tmp = 100;
  }

  function changeStorage(){
    var tmp = refrenceType;
    tmp[1] = 100;
  }

  function getAll() returns (uint, uint){
    return (valueType, refrenceType[1]);
  }
}

下面来看下官方的例子说明:

pragma solidity ^0.4.0;

contract C {
    uint[] x; // the data location of x is storage

    // the data location of memoryArray is memory
    function f(uint[] memoryArray) {
        x = memoryArray; // works, copies the whole array to storage
        var y = x; // works, assigns a pointer, data location of y is storage
        y[7]; // fine, returns the 8th element
        y.length = 2; // fine, modifies x through y
        delete x; // fine, clears the array, also modifies y
        // The following does not work; it would need to create a new temporary /
        // unnamed array in storage, but storage is "statically" allocated:
        // y = memoryArray;
        // This does not work either, since it would "reset" the pointer, but there
        // is no sensible location it could point to.
        // delete y;
        g(x); // calls g, handing over a reference to x
        h(x); // calls h and creates an independent, temporary copy in memory
    }

    function g(uint[] storage storageArray) internal {}
    function h(uint[] memoryArray) {}
}

总结

强制的数据位置(Forced data location)

  • 外部函数(External function)的参数(不包括返回参数)强制为:calldata
  • 状态变量(State variables)强制为: storage

默认数据位置(Default data location)

  • 函数参数(括返回参数:memory
  • 所有其它的局部变量:storage

更多请查看关于数据位置的进一步挖掘: http://me.tryblockchain.org/solidity-data-location.html

参考资料


  1. 本地变量但是为什么是stroage的,没有太想明白。 http://ethereum.stackexchange.com/questions/9781/solidity-default-data-location-for-local-vars 

处于某些特定的环境下,可以看到评论框,欢迎留言交流^_^。