# 數據位置(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)
- Solidity語言
- 入門說明
- Solidity智能合約文件結構
- 智能合約源文件的基本要素概覽
- 值類型
- 類型
- 布爾
- 整型
- 地址
- 字節數組
- 小數
- 字符串
- 十六進制字面量
- 枚舉
- 函數
- 引用類型
- 引用類型
- 數據位置
- 數組
- 數據結構
- 雜項
- 映射
- 左值運算符
- 類型間的轉換
- 類型推斷
- 單位
- 貨幣單位
- 時間單位
- 語言內置特性
- 特殊變量及函數
- 數學和加密函數
- 地址相關
- 進階
- 入參和出參
- 控制結構
- 函數調用
- 創建合約實例
- 表達式的執行順序
- 賦值
- 作用范圍和聲明
- 異常
- 內聯匯編
- 合約詳解
- 合約
- 可見性或權限控制
- 訪問函數
- 函數修改器
- 常狀態變量
- 回退函數
- 事件
- 繼承
- 接口
- 其它
- 庫
- 狀態變量的存儲模型
- 內存變量的存局
- 調用數據的布局