本文首發於深刻淺出區塊鏈社區 原文連接:智能合約語言 Solidity 教程系列4 - 數據存儲位置分析原文已更新,請讀者前往原文閱讀html
Solidity 是以太坊智能合約編程語言,閱讀本文前,你應該對以太坊、智能合約有所瞭解, 若是你還不瞭解,建議你先看以太坊是什麼編程
這部分的內容官方英文文檔講的不是很透,所以我在參考Solidity官方文檔(當前最新版本:0.4.20)的同時加入了深刻分析部分,歡迎訂閱專欄。數組
在系列第一篇,咱們提到 Solidity 類型分爲兩類: 值類型(Value Type) 及 引用類型(Reference Types), 前面咱們已經介紹完了值類型,接下來會介紹引用類型。數據結構
引用類型是一個複雜類型,佔用的空間一般超過256位, 拷貝時開銷很大,所以咱們須要考慮將它們存儲在什麼位置,是memory(內存中,數據不是永久存在)仍是storage(永久存儲在區塊鏈中) 全部的複雜類型如數組(arrays)和結構體(struct)有一個額外的屬性:數據的存儲位置(data location)。可爲memory和storage。編程語言
根據上下文的不一樣,大多數時候數據位置有默認值,也經過指定關鍵字storage和memory修改它。函數
函數參數(包含返回的參數)默認是memory。 局部複雜類型變量(local variables)和 狀態變量(state variables) 默認是storage。學習
局部變量:局部做用域(越過做用域即不可被訪問,等待被回收)的變量,如函數內的變量。狀態變量:合約內聲明的公有變量區塊鏈
還有一個存儲位置是:calldata,用來存儲函數參數,是隻讀的,不會永久存儲的一個數據位置。外部函數的參數(不包括返回參數)被強制指定爲calldata。效果與memory差很少。ui
數據位置指定很是重要,由於他們影響着賦值行爲。 在memory和storage之間或與狀態變量之間相互賦值,老是會建立一個徹底獨立的拷貝。 而將一個storage的狀態變量,賦值給一個storage的局部變量,是經過引用傳遞。因此對於局部變量的修改,同時修改關聯的狀態變量。 另外一方面,將一個memory的引用類型賦值給另外一個memory的引用,不會建立拷貝(即:memory之間是引用傳遞)。code
- 注意:不能將memory賦值給局部變量。
- 對於值類型,老是會進行拷貝。
下面看一段代碼:
pragma solidity ^0.4.0; contract C { uint[] x; // x的存儲位置是storage // memoryArray的存儲位置是 memory function f(uint[] memoryArray) public { x = memoryArray; // 從 memory 複製到 storage var y = x; // storage 引用傳遞局部變量y(y 是一個 storage 引用) y[7]; // 返回第8個元素 y.length = 2; // x一樣會被修改 delete x; // y一樣會被修改 // 錯誤, 不能將memory賦值給局部變量 // y = memoryArray; // 錯誤,不能經過引用銷燬storage // delete y; g(x); // 引用傳遞, g能夠改變x的內容 h(x); // 拷貝到memory, h沒法改變x的內容 } function g(uint[] storage storageArray) internal {} function h(uint[] memoryArray) public {} }
storage 存儲結構是在合約建立的時候就肯定好了的,它取決於合約所聲明狀態變量。可是內容能夠被(交易)調用改變。
Solidity 稱這個爲狀態改變,這也是合約級變量稱爲狀態變量的緣由。也能夠更好的理解爲何狀態變量都是storage存儲。
memory 只能用於函數內部,memory 聲明用來告知EVM在運行時建立一塊(固定大小)內存區域給變量使用。
storage 在區塊鏈中是用key/value的形式存儲,而memory則表現爲字節數組
EVM是一個基於棧的語言,棧實際是在內存(memory)的一個數據結構,每一個棧元素佔爲256位,棧最大長度爲1024。 值類型的局部變量是存儲在棧上。
咱們也推出了目前市面上最全的視頻教程:深刻詳解以太坊智能合約語言Solidity 目前咱們也在招募課程體驗師,能夠點擊連接瞭解。
☛ 深刻淺出區塊鏈 - 系統學習區塊鏈,打造最好的區塊鏈技術博客。
☛ 個人知識星球爲各位解答區塊鏈技術問題,歡迎加入討論。
☛ 關注公衆號「深刻淺出區塊鏈技術」第一時間獲取區塊鏈技術信息。