Solidity 赋值的数据位置规则

solidity 数据可以通过两种方式从一个变量复制到另一个变量。

一种方法是复制整个数据(按值复制),另一种方法是引用复制。

solidity 从一个位置的变量赋值到另一个位置的变量,遵循一定的默认规则。

 

1. 规则1 – 状态变量赋值给状态变量

将一个状态变量赋值给另一个状态变量,将创建一个新的副本。

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Locations {  
  uint public stateVar1 = 10;  
  uint public stateVar2 = 20;  

  function do() public returns (uint) {  

   stateVar1 = stateVar2;  
   stateVar2 = 30;  

   return stateVar1; //returns 20  
  }  
} 

本例中,stateVar1 和 stateVar2 是状态变量。

在 do 函数中,我们将 stateVar2 的值赋值给 stateVar1。

stateVar1 的值是 20,但是为了确定它创建了一个新的副本,我们改变了stateVar2 的值。因此,如果它不创建副本,那么 stateVar1 的值应该是30,创建副本则是20。

这同样适用于引用类型的状态变量。

 

2. 规则2 – 内存局部变量复制到状态变量

从内存局部变量复制到状态变量,总是会创建一个新的副本。

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Locations {
    uint stateVar = 10; //storage

    function do() public returns(uint) {
        uint localVar = 20; //memory    
        stateVar = localVar;  
        localVar = 40;

        return stateVar; //returns 20    
    }  
}  

在上面的例子中,我们有一个状态变量和一个局部内存变量。在函数中,我们把局部变量的值赋给状态变量。

为了检查赋值后的行为,我们改变了局部变量的值,并返回状态变量的值。

这里可以看到,它会返回20,说明从内存局部变量复制到状态变量,会创建一个新的副本。

 

3. 规则3 – 状态变量复制到内存局部变量

从状态变量复制到内存局部变量,将创建一个副本。

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Locations {
    uint stateVar = 10; //storage

    function do() public returns(uint) {
        uint localVar = 20; //memory    

        localVar = stateVar;  
        stateVar = 40;  

        return localVar; //returns 10    
    }  
} 

在这里,将状态变量的值赋给了内存局部变量,并改变了状态变量的值。为了检查局部变量的值是否已经更改,返回它的值。

我们部署运行后,调用 do 会返回10,说明从状态变量复制到内存局部变量,将创建一个副本。

 

4. 规则4 – 内存变量复制到内存变量

对于引用类型的局部变量,从一个内存变量复制到另一个内存变量,不会创建副本。

对于值类型的局部变量,从一个内存变量复制到另一个内存变量,仍然创建一个新副本。

引用类型

// SPDX-License-Identifier: MIT
pragma solidity ^ 0.8.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。

值类型

// SPDX-License-Identifier: MIT
pragma solidity ^ 0.8.0;  

contract Locations {  
    function do() public pure returns(uint) {
        uint localVar1 = 10; //memory    
        uint localVar2 = 20; //memory

        localVar1 = localVar2;  
        localVar2 = 40;

        return localVar1; //returns 20    
    }  
}

函数是一组可重用代码的包装,接受输入,返回输出。Solidity 支持函数定义和调用。1. 函数定义Solidity中, 定义函数的语法如下:语法function function_name(<paramete ...