經過本文學習,熟悉瞭解以太坊智能合約語言Solidity語法中constant,view,pure的區別。html
在Solidity中constant,view,pure三個函數修飾詞的做用是告訴編譯器,函數不改變/不讀取狀態變量,這樣函數執行就能夠不消耗gas了(是徹底不消耗!),由於不須要礦工來驗證。ide
在Solidity v4.17以前,只有constant,後來有人嫌constant這個詞自己表明變量中的常量,不適合用來修飾函數,因此將constant拆成了view和pure。函數
view的做用和constant如出一轍,能夠讀取狀態變量可是不能改;學習
pure則更爲嚴格,pure修飾的函數不能改也不能讀狀態變量,不然編譯通不過。區塊鏈
你們能夠運行如下測試代碼來加深這3個關鍵字的理解。測試
contract constantViewPure{ string name; uint public age; function constantViewPure() public{ name = "liushiming"; age = 29; } function getAgeByConstant() public constant returns(uint){ age += 1; //聲明爲constant,在函數體中又試圖去改變狀態變量的值,編譯會報warning, 可是能夠經過 return age; // return 30, 可是!狀態變量age的值不會改變,仍然爲29! } function getAgeByView() public view returns(uint){ age += 1; //view和constant效果一致,編譯會報warning,可是能夠經過 return age; // return 30,可是!狀態變量age的值不會改變,仍然爲29! } function getAgeByPure() public pure returns(uint){ return age; //編譯報錯!pure比constant和view都要嚴格,pure徹底禁止讀寫狀態變量! return 1; } }
2.1 Constant 狀態變量優化
狀態變量能夠被聲明爲 constant。在這種狀況下,只能使用那些在編譯時有肯定值的表達式來給它們賦值。 任何經過訪問 storage,區塊鏈數據(例如 now, this.balance 或者 block.number)或執行數據( msg.gas ) 或對外部合約的調用來給它們賦值都是不容許的。 在內存分配上有邊界效應(side-effect)的表達式是容許的,但對其餘內存對象產生邊界效應的表達式則不行。 內建(built-in)函數 keccak256,sha256,ripemd160,ecrecover,addmod 和 mulmod 是容許的(即便他們確實會調用外部合約)。ui
容許帶有邊界效應的內存分配器的緣由是這將容許構建複雜的對象,好比查找表(lookup-table)。 此功能還沒有徹底可用。this
編譯器不會爲這些變量預留存儲,它們的每次出現都會被替換爲相應的常量表達式(這將可能被優化器計算爲實際的某個值)。code
不是全部類型的狀態變量都支持用 constant 來修飾,當前支持的僅有值類型和字符串。
pragma solidity ^0.4.0; contract C { uint constant x = 32**22 + 8; string constant text = "abc"; bytes32 constant myHash = keccak256("abc"); }
2.2 View 函數
能夠將函數聲明爲 view 類型,這種狀況下要保證不修改狀態。
下面的語句被認爲是修改狀態:
修改狀態變量。
產生事件(https://solidity-cn.readthedocs.io/zh/develop/contracts.html?highlight=view#events)。
建立其它合約(https://solidity-cn.readthedocs.io/zh/develop/control-structures.html#creating-contracts)。
使用 selfdestruct。
經過調用發送以太幣。
調用任何沒有標記爲 view 或者 pure 的函數。
使用低級調用。
使用包含特定操做碼的內聯彙編。
pragma solidity ^0.4.16; contract C { function f(uint a, uint b) public view returns (uint) { return a * (b + 42) + now; } }
註解:
onstant 是 view 的別名。
Getter 方法被標記爲 view。
編譯器沒有強制 view 方法不能修改狀態。
2.3 Pure 函數
函數能夠聲明爲 pure ,在這種狀況下,承諾不讀取或修改狀態。
除了上面解釋的狀態修改語句列表以外,如下被認爲是從狀態中讀取:
讀取狀態變量。
訪問 this.balance 或者 <address>.balance。
訪問 block,tx, msg 中任意成員 (除 msg.sig 和 msg.data 以外)。
調用任何未標記爲 pure 的函數。
使用包含某些操做碼的內聯彙編。
pragma solidity ^0.4.16; contract C { function f(uint a, uint b) public pure returns (uint) { return a * (b + 42); } }
警告
編譯器沒有強制 pure 方法不能讀取狀態。
本文做者:HiBlock區塊鏈社區技術佈道者輝哥
原文發佈於簡書
區塊鏈馬拉松|Blockathon(2018)上海 邀請你來觀看路演啦~
如下是咱們的社區介紹,歡迎各類合做、交流、學習:)