區塊鏈100講:Solidity語法constant/view/pure關鍵字定義
通過本文學習,熟悉瞭解以太坊智慧合約語言Solidity語法中constant,view,pure的區別。
1
區別總結
在Solidity中constant,view,pure三個函式修飾詞的作用是告訴編譯器,函式不改變/不讀取狀態變數,這樣函式執行就可以不消耗gas了(是完全不消耗!),因為不需要礦工來驗證。
在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
詳細描述
2.1 Constant 狀態變數
狀態變數可以被宣告為 constant。在這種情況下,只能使用那些在編譯時有確定值的表示式來給它們賦值。 任何通過訪問 storage,區塊鏈資料(例如 now, this.balance 或者 block.number)或執行資料( msg.gas ) 或對外部合約的呼叫來給它們賦值都是不允許的。 在記憶體分配上有邊界效應(side-effect)的表示式是允許的,但對其他記憶體物件產生邊界效應的表示式則不行。 內建(built-in)函式 keccak256,sha256,ripemd160,ecrecover,addmod 和 mulmod 是允許的(即使他們確實會呼叫外部合約)。
允許帶有邊界效應的記憶體分配器的原因是這將允許構建複雜的物件,比如查詢表(lookup-table)。 此功能尚未完全可用。
編譯器不會為這些變數預留儲存,它們的每次出現都會被替換為相應的常量表達式(這將可能被優化器計算為實際的某個值)。
不是所有型別的狀態變數都支援用 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 或者
.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區塊鏈社群技術佈道者輝哥
原文釋出於簡書
以下是我們的社群介紹,歡迎各種合作、交流、學習:)