【发布时间】:2016-02-23 16:14:53
【问题描述】:
在查看示例合同时,有时数组是在具有“内存”的方法中声明的,有时则不是。有什么区别?
【问题讨论】:
在查看示例合同时,有时数组是在具有“内存”的方法中声明的,有时则不是。有什么区别?
【问题讨论】:
如果没有 memory 关键字,Solidity 会尝试在 storage 中声明变量。
Lead Solidity dev chriseth:“您可以将存储视为具有虚拟结构的大型数组......您无法在运行时更改的结构 - 它由合约中的状态变量决定”。
也就是说,存储结构在创建合约时根据您的合约级变量声明一成不变,并且不能被未来的方法调用更改。但是——可以通过 sendTransaction 调用更改该存储的内容。这样的调用会改变“状态”,这就是为什么合约级别的变量被称为“状态变量”。所以一个变量 uint8 storagevar;可以将在合约级别声明的任何有效值更改为 uint8 (0-255),但类型为 uint8 的值的“槽”将始终存在。
如果你在没有memory关键字的函数中声明变量,那么solidity会尝试使用当前可以编译的存储结构,但是会产生意想不到的结果。 memory 告诉solidity 在方法运行时为变量创建一块空间,保证它的大小和结构以供将来在该方法中使用。
内存不能在合约级别使用。仅在方法中。
请参阅常见问题解答中的the entry "What is the memory keyword? What does it do?"。我在这里引用它:
以太坊虚拟机具有三个可以存储物品的区域。
第一个是“存储”,所有合约状态变量都驻留在其中。每个合约都有自己的存储,并且在函数调用之间是持久的,并且使用起来非常昂贵。
第二个是“内存”,用于保存临时值。它在(外部)函数调用之间被删除并且使用成本更低。
第三个是栈,用来存放小的局部变量。它几乎可以免费使用,但只能保存有限数量的值。
对于几乎所有类型,您无法指定它们的存储位置,因为它们每次使用时都会被复制。
所谓存储位置很重要的类型是结构体和数组。如果你例如在函数调用中传递此类变量,如果它们的数据可以保留在内存中或保留在存储中,则不会复制它们的数据。这意味着您可以在被调用函数中修改它们的内容,并且这些修改在调用者中仍然可见。
存储位置有默认值,具体取决于它涉及的变量类型:
- 状态变量始终在存储中
【讨论】:
memory 关键字?如果内存是短暂的,那么使用它的原因是什么?合约如何在部署后仍然调用这些函数并因此修改内存?
memory 定义了 Solidity 中的数据位置之一,它只能在运行时临时保存值。
Solidity 中的memory 变量只能在方法中声明,通常用于方法参数。一个不能保存在区块链中的短期变量......它只在函数执行期间保存值,并且它的值在执行后销毁。
看看示例函数f(),其中我使用memory关键字声明了一个指针。它不会改变变量User的值,而如果它是使用storage声明的,它将改变变量User的值存储在区块链中,值不会被销毁...
struct User {
string name;
}
User[] users;
function f() external {
User memory user = users[0]; // create a pointer
user.name = "example name" // can't change the value of struct User
}
【讨论】:
存储在函数调用之间保存数据。它就像电脑硬盘。变量是存储数据
内存临时存储数据的地方,如 RAM。函数 args 是内存数据
假设一个数组是一种存储类型
// state variables are placed in Storage
int[] public numbers
function Numbers()public{
numbers.push(5)
numbers.push(10)
int[] storage myArray=numbers
// numbers[0] will also be changed to 1
myArray[0]=1
}
int[] storage myArray=numbers 在这种情况下 myArray 将指向与“数字”相同的地址。 (它类似于引用对象在 javascript 中的行为方式)。请参阅我将 5 和 10 添加到存储中的“数字”的功能。但是如果你在remix上部署代码并得到numbers[0],你会得到1,因为myArray[0]=1
如果您将 myArray 定义为内存,那将是另一回事。
// state variables are placed in Storage
int[] public numbers
function Numbers() public{
numbers.push(5)
numbers.push(10)
int[] memory myArray=numbers
myArray[0]=1
}
在这种情况下,“numbers”数组被复制到内存中,myArray 现在引用了一个不同于“numbers”地址的内存地址。如果您部署此代码并到达numbers[0],您将获得 5。
【讨论】:
int[] storage myArray 只是一个指向 numbers 变量的指针,并且没有为 myArray 保留存储空间。将 myArray 分配给数字的 gas 成本是多少?