2018-10-24筆記
對于變量類型做了一些試驗(yàn)递瑰,得到一下一些結(jié)論:
- 根據(jù)傳遞方式來分,變量種類有按值傳遞與按引用傳遞兩種類型,引用類型有
arrays
报咳、structs
、mappings
挖藏。根據(jù)聲明位置分暑刃,主要有狀態(tài)變量(相當(dāng)于全局變量),局部變量膜眠。 - 狀態(tài)變量的數(shù)據(jù)存儲區(qū)都是
storage
岩臣,并且Mappings
只可以聲明為狀態(tài)變量。 - 作為函數(shù)局部變量的引用類型變量(為了方便敘述婿脸,下用uint[]舉例粱胜,
structs
是一樣的焙压,可以自己做一下試驗(yàn))在塔,在0.5之前幻件,如果沒有指定存儲區(qū),則默認(rèn)存儲區(qū)為storage
蛔溃,且是作為“指針”的形式存在绰沥,如果聲明的時候沒有進(jìn)行初始化,編譯器會出現(xiàn)警告贺待,此時默認(rèn)指向storage
的第一個slot
徽曲;
實(shí)驗(yàn)舉例
開始做試驗(yàn),假設(shè)有如下合約麸塞,
pragma solidity ^0.4.0;
contract hello {
uint a = 1234;
uint[] d_arr;
function sayhi() public returns(uint) {
uint[] p;
p.push(1000);
return a;
}
}
查看編譯器有如下警報:
下面證明默認(rèn)指向的位置為storage
的第一個slot秃臣,將合約部署,然后調(diào)用sayhi()方法哪工,可以得到:
從圖中可以看到a
的值變成了1235
奥此,在合約中我們并沒有操作a
,我們只執(zhí)行了一次push
操作(這個操作會將.length
的值加1
)雁比,因此可以斷定稚虎,p
指向了a
,并且a
在storage
的第一個slot中(關(guān)于這點(diǎn)放在變量布局中講)章贞。
將合約稍微改一下:
pragma solidity ^0.4.0;
contract hello {
uint a = 1234;
uint[] d_arr;
function sayhi() public returns(uint) {
uint[] memory p=d_arr;
p.push(1000);
return a;
}
}
我們將p
的存儲區(qū)顯式指定為memory
祥绞,會看到編譯器的報錯:
從報錯中可以看到,memory
中不可以使用push
操作(pop
也不可以)鸭限,另外使用new
聲明的數(shù)組蜕径,雖然可以在運(yùn)行時候指定數(shù)組的長度,但是聲明后依舊不可以修改數(shù)組的length
值败京,下面是對官方文檔的引用:
You can use the new keyword to create arrays with a runtime-dependent length in memory. As opposed to storage arrays, it is not possible to resize memory arrays.
下面再看一下兜喻,從storage
到memory
的引用類型變量的傳遞情況。
pragma solidity ^0.4.0;
contract hello {
uint a = 1234;
uint[] d_arr = [123, 456];
function sayhi() public view returns(uint, uint) {
uint[] memory p=d_arr;
p[0] = 321;
return (p[0], d_arr[0]);
}
}
部署赡麦、調(diào)用sayhi
朴皆,查看返回值
可以看到將狀態(tài)變量中的array
賦值給局部變量中的array
帕识,會將storage
中的array
拷貝一份到memory
中。
從局部變量到狀態(tài)變量顯而易見就是拷貝了遂铡,因?yàn)?code>memory在每次方法運(yùn)行前肮疗,都會"清洗"干凈。
pragma solidity ^0.4.0;
contract hello {
uint a = 1234;
uint[] d_arr;
function sayhi() public returns(uint, uint) {
uint[3] memory p = [uint(1),2,3];
d_arr = p;
p[0] = 123;
return (p[0], d_arr[0]);
}
}
同樣扒接,storage
到storage
也是拷貝伪货,因?yàn)?code>storage存的是狀態(tài)變量,對其做的修改應(yīng)該得到保存钾怔。
pragma solidity ^0.4.0;
contract hello {
uint a = 1234;
uint[] d_arr = [1, 2, 3];
uint[] d_arr1 = [4, 5, 6];
function sayhi() public returns(uint, uint) {
d_arr1 = d_arr;
d_arr[0] = 100;
return (d_arr[0], d_arr1[0]);
}
}
部署碱呼、調(diào)用,輸出結(jié)果為:
引用類型在狀態(tài)變量跟局部變量之間的傳遞方式如下圖所示:
因?yàn)椴幌胫匦滦薷纳厦婺菑垐D宗侦,直接補(bǔ)充在這里好了愚臀。
對于memory
跟memory
之間的傳遞方式時傳遞引用。
pragma solidity ^0.4.0;
contract hello {
function sayhi() public pure returns(uint, uint) {
uint[3] memory p1 = [uint(1), 2, 3];
uint[3] memory p2 = [uint(4), 5, 5];
p1 = p2;
p2[0] = 10;
return (p1[0], p2[0]);
}
}