所有的引用类型都有一个额外注解(storage、memory、calldata),来说明数据的存储位置,上节提到的mapping、struct、array都是引用类型
storage
- storage变量永久存储在区块链上memory
- memory变量则是临时的,当函数调用完成时被移除calldata
- 效果同memory,只不过用在external函数调用中
数据存储位置不同,赋值行为也会不同,下面看几个案例:
-
storage to storage
storage状态变量 -> storage状态变量 之间赋值是通过值拷贝,对一个变量值的修改不会影响另一个变量
storage状态变量 -> storage局部变量 之间赋值是通过引用传递,对一个变量值的修改会影响另一个变量
contract LocationTest { struct person{ string name; } person p1; person p2; function f() public{ person storage p3 = p1; //p3是一个storage point p3.name = "A"; //此时 p1.name = A p2 = p3; //同p2 = p1,这里只是赋值 p3.name = "B"; //此时 p1.name = B ,p2.name = A } }
2.memory to memory
memory -> memory 之间赋值是通过引用传递,对一个变量值的修改会影响另一个变量
contract LocationTest { struct person{ string name; } function f() public{ person memory p1 = person("A"); person memory p2 = p1; p2.name = "B"; //p2.name = B ,p1.name= B } }
-
storage to memory
memory -> storage状态变量 之间赋值是通过值拷贝,对一个变量值的修改不会影响另一个变量
memory 无法赋值给 storage 局部变量,因为 storage 局部变量 是一个storage point
contract LocationTest { struct person{ string name; } person p1; function f() public{ person memory p2 = person("A"); p1 = p2; p2.name = "B"; //p1.name =A ;p2.name= B // person storage p3 = p2; 不能赋值 } function get() public view returns(string memory){ return p1.name; } }
-