對於複雜類型例如array,struct都有一個都有一個額外的註解(annotation),多是storage,memory,calldata之一。根據上下文老是有一個默認的註解類型。可是通常能夠經過storage和memory關鍵字顯示的修改。數組
對於函數的出參和入參通常默認的是memory類型(external 函數的入參例外是強制的calldata類型)函數
對於局部變量默認的是storage類型(能夠經過memory修改)區塊鏈
對於狀態變量強制的是storage類型(不能經過memory修改)ui
會寫入區塊鏈中指針
不會持久化(不會寫入到區塊鏈中)code
不可修改,不可持久化orm
pragma solidity ^0.4.18; contract DL{ uint [] stateVariable;//狀態變量(state variable) function normal(uint [] inArg) public returns(uint outArg){ uint [] localVar;//局部變量(本地變量,local variable) return 0; } function cd(uint [] inArg) external returns(uint outArg){ return 0; } }
上面代碼的stateVariable就是狀態變量,inArg就是入參,outArg就是出參string
stateVariable的data location就是storageit
localVar是局部變量,data location是memoryio
函數normal的inArg的data location是memory outArg也是memory
函數cd的inArg的data location是calldata outArg是memory
function storaegPara(Person storage allen) public returns(uint8 age,string name){ person = allen; return (person.age,person.name); }
像上面這種就會出編譯錯誤。
pragma solidity ^0.4.18; contract DL{ struct Person{ uint8 age; string name; } Person person = Person({age:20,name:"tim"});//狀態變量,強制storage(state variable) function storaegPara(Person storage allen) internal returns(uint8 age,string name){ person = allen; return (person.age,person.name); } function testStoraegPara() returns(uint8 age,string name){ Person allen = Person({age:22,name:"allen"}); return storaegPara(allen); } }
像上面的就會編譯錯誤。從前面咱們知道:
Person allen = Person({age:22,name:"allen"});
等價於:
Person memory allen = Person({age:22,name:"allen"});
當調用storaegPara(allen)的時候,至關於把一個memory的局部allen變量賦值給一個storage的局部變量allen。
這是由於storage是靜態分配存儲空間的,對於storage的賦值,更像是對指針的賦值。
pragma solidity ^0.4.18; contract DL{ struct Person{ uint8 age; string name; } Person person = Person({age:20,name:"tim"});//狀態變量,強制storage(state variable) function storaegPara(Person memory allen) internal returns(uint8 age,string name){ person = allen; return (person.age,person.name); } function testStoraegPara() returns(uint8 age,string name){ Person memory allen = Person({age:22,name:"allen"}); return storaegPara(allen); } }
storage能夠對memory進行賦值,執行的是拷貝操做。(修改新的memory變量不會影響原來storage變量)
memory對memory的賦值是引用
同類賦值(memory對memory,storage對storage)是引用,至關於指針不會執行數據拷貝。
memory和storage相互賦值,執行的是數據拷貝,可是注意memory不能對局部storage賦值
對於變長數組必須使用new初始化以後才能訪問
new 產生的是memory類型的,不能轉換爲局部的storage,因此能夠看到在函數中下面的代碼是會出編譯錯誤的:
uint [] storage data = new uint[](1);
對於storage的變長數組,能夠經過給length賦值調整數組長度。還能夠使用後面提到的push()方法,來隱式的調整數組長度
對於memory的變長數組,不支持修改length屬性,來調整數組大小。memory的變長數組雖然能夠經過參數靈活指定大小,但一旦建立,大小不可調整