详述Solidity数据类型之二:引用类型

点此注册【火币交易所】享受更低的手续费
比特币价格未来将破10万元,快速买卖比特币  

作者:梁雁明

著权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

引用类型

复杂类型例如不能匹配256bit类型,而且必须要被比我们已经知道的值类型更加小心处理的类型.因为复制值类型是代价是高昂的,所以我们必须试想如何在内部中(非实例化)或存储它们。

数据位置

每一个复杂的类型,像 arrays structs都有额外的标注"data location", 关于它们是保存在内部中还是存储中根据上下文环境总有默认值,当然可以通过追加关键字storage  memory去进行覆盖.函数参数(包括返回类型)的默认类型是 memory而本地变量的默认类型是 storage ,而且状态变量的位置标注会被强制转化为 storage (明显的).

还有第三种位置类型标注calldata当函数变量被保存时,是不可改变及不可持久化的外部函数参数(非返回参数强制为 calldata 而行为方式与 memory相类似。

数据位置标注是很重要的,因为他可以改变分配的行为方式: storagememory之间的分配,而且,一个状态变量(即使从别的状态变量而来的总是生成一份独立的数据复制区域对于本地存储变量的分配只是分配引用这一引用总是指向即使后者会被同时被改变的状态变量上,别一方面,内存存储引用类型的分配到另一内存存储引用并不会产生数据复制。

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) public {
        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) public {}
}

总结

固定的数据位置:

·       外部函数的参数(非返回参数): calldata

·       态变: storage

的数据位置:

·       函数参数(包括返回参数): memory

·       所有本地: storage

·      

·      数组在编译期间有固定的大小或者数组可以动态变化.对于存储数组其元素类型是任意的(例如别的arrays, mappings structs). 对于内存数组其元素不能是mapping ,而且如果其成员是公共可见函数,还必须是ABI 类型的一种。

固定大小 k 且元素类型为 T 的数组书写形式为 T[k],动态大小数组的书写形式为 T[]举例说明,一个包括5个动态 uint 数组的数组表式为uint[][5] (与其它言相比,标记顺序是相反的).你可以使用x[2][1] 得第三个数中的第二个元素(基于0取方式与声明相反的形式i.e. x[2] shaves off one level in the type from the right).

·      bytes  string 是比较特殊的数组.  bytes 等价于 byte[],calldata中被打包了string 等价于 bytes 不允许长度或下标的索引获取(目前).

·      所以 bytes 是优于 byte[] 使用的,因为它更省开销.

·       注解

·       如果你想获得字符串s的字节表示形式那么你可以使用如下方式: bytes(s).length / bytes(s)[7] = 'x';请牢记你将获得到的是低等级的UTF-8字节表示,并不包括其它特殊的字符!

·      可以为数据标记为public 而且Solidity会为其创建一个 getter方法在调用getter方法时,数字下标是被要求的.

·      分配内存数

·      可以通过使用new 关键字在内存中创建可变长度的数组与storage 数组相对不可以向通过指 .length 成员来重新定义memory数组的大小.

·      pragma solidity ^0.4.16;

·      contract C {

·          function f(uint len) public pure {

·              uint[] memory a = new uint[](7);

·              bytes memory b = new bytes(len);

·              // Here we have a.length == 7 and b.length == len

·              a[6] = 8;

·          }

·       }

·      常量/

·      数组常量是当前未被分配到任何变量,并以表达式形式表示的数组.

·      pragma solidity ^0.4.16;

·      contract C {

·          function f() public pure {

·              g([uint(1), 2, 3]);

·          }

·          function g(uint[3] _data) public pure {

·              // ...

·          }

·       }

·      常量数组类型是一个通常元素类型且固定大小的内存数组.  [1, 2, 3] 的类型为 uint8[3] memory因为数组的每一个常量类型是 uint8.基于此,必然可以将第一个元素存放在上面的 uint请注意当前,固定大小的内存数组不能被指向于一个动态大小的内存数组,示例如下,这种方式是不被允许的:

·      // This will not compile.

·      pragma solidity ^0.4.0;

·      contract C {

·          function f() public {

·              // The next line creates a type error because uint[3] memory

·              // cannot be converted to uint[] memory.

·              uint[] x = [uint(1), 3, 4];

·          }

·       }

·      本来打算是要将这限制人未来一段时间去掉的,但是目前,在处理数组如何在ABI传递时出现了一些难题.

·      

·       length:

·       length 表示成的个数动态可以在storage(not in memory)改变 .length 重新指定大小尝试以超过数组大小的方式获得数元素种方式不会自动执行,内存数的大小在就被固定了(但如果是动态,依于其运行的参数)

·       push:

·      动态storage 组和bytes (而不是string有名push 的成方法,用于在数尾部追回元素函数返回数的最新.

·       警告

·       目前尚不能在外部函数中使用数组的数组(多维数组).

·       警告

·       基于EVM的限制可能够从外部的函数调用返回动态内容函数f contract C { function f() returns (uint[]) { ... } } web3.js调用的话,会返回一些值但在Solidity中使用时不会返回任何东西.

·       The only workaround for now is to use large statically-sized arrays.

·      pragma solidity ^0.4.16;

·      contract ArrayContract {

·          uint[2**20] m_aLotOfIntegers;

·          // Note that the following is not a pair of dynamic arrays but a

·          // dynamic array of pairs (i.e. of fixed size arrays of length two).

·          bool[2][] m_pairsOfFlags;

·          // newPairs is stored in memory - the default for function arguments

·       

 

·          function setAllFlagPairs(bool[2][] newPairs) public {

·              // assignment to a storage array replaces the complete array

·              m_pairsOfFlags = newPairs;

·          }

·          function setFlagPair(uint index, bool flagA, bool flagB) public {

·              // access to a non-existing index will throw an exception

·              m_pairsOfFlags[index][0] = flagA;

·              m_pairsOfFlags[index][1] = flagB;

·          }

·          function changeFlagArraySize(uint newSize) public {

·              // if the new size is smaller, removed array elements will be cleared

·              m_pairsOfFlags.length = newSize;

·          }

·          function clear() public {

·              // these clear the arrays completely

·              delete m_pairsOfFlags;

·              delete m_aLotOfIntegers;

文章发布只为分享区块链技术内容,版权归原作者所有,观点仅代表作者本人,绝不代表区块链兄弟赞同其观点或证实其描述。

1 推荐
打赏 收藏





本文由 区块链技术网 作者:区块链 发表,其版权均为 区块链技术网 所有,文章内容系作者个人观点,不代表 区块链技术网 对观点赞同或支持。如需转载,请注明文章来源。

发表评论