智能合約語(yǔ)言 Solidity 教程系列4 - 數(shù)據(jù)存儲(chǔ)位置分析

最新內(nèi)容會(huì)更新在主站深入淺出區(qū)塊鏈社區(qū)
原文鏈接:智能合約語(yǔ)言 Solidity 教程系列4 - 數(shù)據(jù)存儲(chǔ)位置分析

Solidity教程系列第4篇 - Solidity數(shù)據(jù)位置分析。

寫在前面

Solidity 是以太坊智能合約編程語(yǔ)言,閱讀本文前,你應(yīng)該對(duì)以太坊、智能合約有所了解,
如果你還不了解,建議你先看以太坊是什么

這部分的內(nèi)容官方英文文檔講的不是很透,因此我在參考Solidity官方文檔(當(dāng)前最新版本:0.4.20)的同時(shí)加入了深入分析部分,歡迎訂閱專欄

數(shù)據(jù)位置(Data location)

在系列第一篇,我們提到 Solidity 類型分為兩類:
值類型(Value Type)引用類型(Reference Types)
前面我們已經(jīng)介紹完了值類型,接下來會(huì)介紹引用類型。

引用類型是一個(gè)復(fù)雜類型,占用的空間通常超過256位, 拷貝時(shí)開銷很大,因此我們需要考慮將它們存儲(chǔ)在什么位置,是memory(內(nèi)存中,數(shù)據(jù)不是永久存在)還是storage(永久存儲(chǔ)在區(qū)塊鏈中)
所有的復(fù)雜類型如數(shù)組(arrays)和數(shù)據(jù)結(jié)構(gòu)(struct)有一個(gè)額外的屬性:數(shù)據(jù)的存儲(chǔ)位置(data location)。可為memorystorage

根據(jù)上下文的不同,大多數(shù)時(shí)候數(shù)據(jù)位置有默認(rèn)值,也通過指定關(guān)鍵字storage和memory修改它。

函數(shù)參數(shù)(包含返回的參數(shù))默認(rèn)是memory
局部復(fù)雜類型變量(local variables)和 狀態(tài)變量(state variables) 默認(rèn)是storage

局部變量:局部作用域(越過作用域即不可被訪問,等待被回收)的變量,如函數(shù)內(nèi)的變量。狀態(tài)變量:合約內(nèi)聲明的公有變量

還有一個(gè)存儲(chǔ)位置是:calldata,用來存儲(chǔ)函數(shù)參數(shù),是只讀的,不會(huì)永久存儲(chǔ)的一個(gè)數(shù)據(jù)位置。外部函數(shù)的參數(shù)(不包括返回參數(shù))被強(qiáng)制指定為calldata。效果與memory差不多。

數(shù)據(jù)位置指定非常重要,因?yàn)樗麄冇绊懼x值行為。
在memory和storage之間或與狀態(tài)變量之間相互賦值,總是會(huì)創(chuàng)建一個(gè)完全獨(dú)立的拷貝。
而將一個(gè)storage的狀態(tài)變量,賦值給一個(gè)storage的局部變量,是通過引用傳遞。所以對(duì)于局部變量的修改,同時(shí)修改關(guān)聯(lián)的狀態(tài)變量。
另一方面,將一個(gè)memory的引用類型賦值給另一個(gè)memory的引用,不會(huì)創(chuàng)建拷貝(即:memory之間是引用傳遞)。

  1. 注意:不能將memory賦值給局部變量。
  2. 對(duì)于值類型,總是會(huì)進(jìn)行拷貝。

下面看一段代碼:

pragma solidity ^0.4.0;

contract C {
    uint[] x; //  x的存儲(chǔ)位置是storage

    // memoryArray的存儲(chǔ)位置是 memory
    function f(uint[] memoryArray) public {
        x = memoryArray;    // 從 memory 復(fù)制到 storage
        var y = x;          // storage 引用傳遞局部變量y(y 是一個(gè) storage 引用)
        y[7];               // 返回第8個(gè)元素
        y.length = 2;       // x同樣會(huì)被修改
        delete x;           // y同樣會(huì)被修改

        // 錯(cuò)誤, 不能將memory賦值給局部變量
        // y = memoryArray;  

        // 錯(cuò)誤,不能通過引用銷毀storage
        // delete y;        

        g(x);               // 引用傳遞, g可以改變x的內(nèi)容
        h(x);               // 拷貝到memory, h無法改變x的內(nèi)容
    }

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

總結(jié)

強(qiáng)制的數(shù)據(jù)位置(Forced data location)

  • 外部函數(shù)(External function)的參數(shù)(不包括返回參數(shù))強(qiáng)制為:calldata
  • 狀態(tài)變量(State variables)強(qiáng)制為: storage

默認(rèn)數(shù)據(jù)位置(Default data location)

  • 函數(shù)參數(shù)及返回參數(shù):memory
  • 復(fù)雜類型的局部變量:storage

深入分析

storage 存儲(chǔ)結(jié)構(gòu)是在合約創(chuàng)建的時(shí)候就確定好了的,它取決于合約所聲明狀態(tài)變量。但是內(nèi)容可以被(交易)調(diào)用改變。

Solidity 稱這個(gè)為狀態(tài)改變,這也是合約級(jí)變量稱為狀態(tài)變量的原因。也可以更好的理解為什么狀態(tài)變量都是storage存儲(chǔ)。

memory 只能用于函數(shù)內(nèi)部,memory 聲明用來告知EVM在運(yùn)行時(shí)創(chuàng)建一塊(固定大小)內(nèi)存區(qū)域給變量使用。

storage 在區(qū)塊鏈中是用key/value的形式存儲(chǔ),而memory則表現(xiàn)為字節(jié)數(shù)組

關(guān)于棧(stack)

EVM是一個(gè)基于棧的語(yǔ)言,棧實(shí)際是在內(nèi)存(memory)的一個(gè)數(shù)據(jù)結(jié)構(gòu),每個(gè)棧元素占為256位,棧最大長(zhǎng)度為1024。
值類型的局部變量是存儲(chǔ)在棧上。

不同存儲(chǔ)的消耗(gas消耗)

  • storage 會(huì)永久保存合約狀態(tài)變量,開銷最大
  • memory 僅保存臨時(shí)變量,函數(shù)調(diào)用之后釋放,開銷很小
  • stack 保存很小的局部變量,幾乎免費(fèi)使用,但有數(shù)量限制。

參考視頻

我們也推出了目前市面上最全的視頻教程:深入詳解以太坊智能合約語(yǔ)言Solidity

目前我們也在招募體驗(yàn)師,可以點(diǎn)擊鏈接了解。

參考資料

Solidity官方文檔-類型

深入淺出區(qū)塊鏈 - 系統(tǒng)學(xué)習(xí)區(qū)塊鏈,打造最好的區(qū)塊鏈技術(shù)博客

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,316評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,481評(píng)論 3 415
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,241評(píng)論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,939評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,697評(píng)論 6 409
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,182評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,247評(píng)論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,406評(píng)論 0 288
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,933評(píng)論 1 334
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,772評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,973評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,516評(píng)論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,209評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,638評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,866評(píng)論 1 285
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,644評(píng)論 3 391
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,953評(píng)論 2 373

推薦閱讀更多精彩內(nèi)容