Solidity 赋值数据位置
数据可以通过两种方式从一个变量复制到另一个变量。一种方法是复制整个数据(按值复制),另一种方法是引用复制。
从一个位置复制数据到另一个位置有一定的默认规则。
规则1 – 存储变量赋值给存储变量
将一个状态(存储)变量赋值给另一个状态(存储)变量,将创建一个新的副本。
pragma solidity ^0.5.0;
contract Locations {
uint public stateVar1 = 10;
uint stateVar2 = 20;
function doSomething() public returns (uint) {
stateVar1 = stateVar2;
stateVar2 = 30;
return stateVar1; //returns 20
}
}
本例中,
stateVar1和
stateVar2是状态变量。在
doSomething函数中,我们将
stateVar2的值复制到
stateVar1。
stateVar1的值是20,但是为了确定它创建了一个新的副本,我们改变了
stateVar2的值。因此,如果它不创建副本,那么
stateVar1的值应该是30,创建副本则是20。
这同样适用于引用类型状态变量。
规则2 – 内存变量复制到存储变量
从内存变量复制到存储变量,总是会创建一个新的副本。
pragma solidity ^ 0.5.0;
contract Locations {
uint statevar = 10; //storage
function doSomething() public returns(uint) {
uint localvar = 20; //memory
statevar = localVar;
localvar = 40;
return stateVar; //returns 20
}
}
在上面的例子中,我们有一个状态变量和一个局部变量。在函数中,我们把局部变量的值赋给状态变量。
为了检查行为,我们改变了局部变量的值; 返回状态变量的值。这里可以看到,它会返回20,说明从内存变量复制到存储状态变量,会创建一个新的副本。
规则3 – 存储变量复制到内存变量
从存储变量复制到内存变量,将创建一个副本。
pragma solidity ^ 0.5.0;
contract Locations {
uint statevar = 10; //storage
function doSomething() public returns(uint) {
uint localvar = 20; //memory
localvar = stateVar;
statevar = 40;
return localVar; //returns 10
}
}
在这里,将状态变量的值赋给了局部变量,并改变了状态变量的值。
为了检查局部变量的值是否已经更改,返回它的值。可以看到,它会返回10,说明从状态存储变量复制到内存变量,将创建一个副本。
规则4 – 内存变量复制到内存变量
对于引用类型的局部变量,从一个内存变量复制到另一个内存变量不会创建副本。
对于值类型的局部变量仍然创建一个新副本。
引用类型
pragma solidity ^ 0.5.0;
contract Locations {
function doSomething()
public pure returns(uint[] memory, uint[] memory) {
uint[] memory localMemoryArray1 = new uint[](3);
localMemoryArray1[0] = 4;
localMemoryArray1[1] = 5;
localMemoryArray1[2] = 6;
uint[] memory localMemoryArray2 = localMemoryArray1;
localMemoryArray1[0] = 10;
return (localMemoryArray1, localMemoryArray2);
//returns 10,4,6 | 10,4,6
}
}
在上面的示例中,我们在内存中初始化了一个名为
localMemoryArray1的数组变量,并赋值为4、5和6、然后,我们将该变量复制到名为
localMemoryArray2的新内存变量中。
然后,我们修改了
localMemoryArray1中第一个索引的值,并返回了两个数组。这将得到相同的结果,因为它们都指向相同的位置。
让我们对值类型进行相同的检查。下面的函数将创建一个新的副本并返回20。
值类型
pragma solidity ^ 0.5.0;
contract Locations {
function doSomething() public pure returns(uint) {
uint localVar1 = 10; //memory
uint localVar2 = 20; //memory
localVar1 = localVar2;
localVar2 = 40;
return localVar1; //returns 20
}
}