Solidity
為什麼沒有返回 x(function setArr)?
pragma solidity >=0.5.0 <0.7.0; contract Example{ uint256[3] x; function setArr(uint256[3] memory y) public returns(uint256[3] memory){ x=y; return getArr(x); } function getArr(uint256[3] storage z) internal pure returns(uint256[3] memory) { return z; } }
簡短的回答:
按照設計,沒有語法可以做到這一點。
長答案:
它的“為什麼”與具有與 CPU 不同的約束的 EVM 有關。
uint256[3] storage z
是一個storage
指針。這意味著它由一個指向邏輯槽的 32 字節指針表示,其餘的儲存佈局是隱式的。這也意味著該功能無法從合約外部訪問。外部的任何東西都不能被信任直接引用儲存位置。
uint256[3] memory
是一個memory
變數。這些是暫時的,並且在函式執行後它們不會持續存在。這暗示了他們生活在其他地方的基本事實。它們在記憶體空間中,而不是儲存空間中。所以……從儲存到記憶體意味著複製數據。由於(至少)兩個原因,它不會自動完成。
- 太多的巫術會阻礙有效契約的設計。這裡的慣用方法,或者如果有明顯多於三個的循環,則可以使開發人員清楚地知道工作正在發生。閱讀、複製和寫作。
你可以:
function getArr(uint256[3] storage z) internal pure returns(uint256[3] memory x) { x[0]=z[0]; x[1]=z[1]; x[2]=z[2]; }
這很清楚。
for(uint i=0; i<3; i++) { ...
也會這樣做,但由於需要更新和檢查i's
狀態以及跳轉,因此成本更高。這導致了第二個原因,即 IMO 更為根本。
- 像這樣的過程具有 O(n) 複雜度,這意味著計算成本與數組的長度成正比。無界循環是一個陷阱,它可以使合約看起來有效,然後大規模失敗。當計算能力基本上是無限的,但在對可用計算資源有硬性限制的情況下,迭代和遞歸是強大的工具。這導致人們重新考慮契約應該做什麼。https://blog.b9lab.com/getting-loopy-with-solidity-1d51794622ad
如果編譯器有高級語法來幫助將意圖轉換為 OPCODE,那麼這個問題就不會消失。EVN 中的所有內容對於固定的工作單元都有固定的成本,這一原則在高級語言中也很明顯。換句話說,如果有一個顯式或隱式的“複製數組”函式,那將是非常危險的。
希望能幫助到你。