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  
  }  
}   

本例中,stateVar1stateVar2是状态变量。在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    
    }  
}


浙ICP备17015664号 浙公网安备 33011002012336号 联系我们 网站地图  
@2019 qikegu.com 版权所有,禁止转载