🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 数据位置(Data location) 复杂类型,如`数组(arrays)`和`数据结构(struct)`在Solidity中有一个额外的属性,数据的存储位置。可选为`memory`和`storage`。 `memory`存储位置同我们普通程序的内存一致。即分配,即使用,越过作用域即不可被访问,等待被回收。而在区块链上,由于底层实现了图灵完备,故而会有非常多的状态需要永久记录下来。比如,参与众筹的所有参与者。那么我们就要使用`storage`这种类型了,一旦使用这个类型,数据将永远存在。 基于程序的上下文,大多数时候这样的选择是默认的,我们可以通过指定关键字`storage`和`memory`修改它。 默认的函数参数,包括返回的参数,他们是`memory`。默认的局部变量是`storage`的。而默认的状态变量(合约声明的公有变量)是`storage`。 另外还有第三个存储位置`calldata`。它存储的是函数参数,是只读的,不会永久存储的一个数据位置。`外部函数`的参数(不包括返回参数)被强制指定为`calldata`。效果与`memory`差不多。 数据位置指定非常重要,因为不同数据位置变量赋值产生的结果也不同。在`memory`和`storage`之间,以及它们和`状态变量`(即便从另一个状态变量)中相互赋值,总是会创建一个完全不相关的拷贝。 将一个`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](http://me.tryblockchain.org/solidity-data-location.html)