注意:这里的关系主要正对于contract合约类型,而对于library又不一样!
关于storage和memory及private、public、internal、external直接的关系
pragma solidity ^0.5.0;
contract Test {
// 全局状态变量默认默认都是storage(存于区块链中,永久存在)
uint int_a = 1;
// 全局复杂引用变量默认都是storage(存于区块链中,永久存在)
uint[] public ref_a = [1,2,3];
// 局部非引用变量或非引用类型参数默认都是memory(存取EVM内存,用完立即销毁)
function local_var(uint x) public {
uint a = 1;
}
// 局部引用变量必须指定storage或memory
function local_ref(uint[] storage s) internal {
// 0.5.0版本以后,局部复杂引用类型变量必须指定storage或memory,且必须赋值
uint[] memory x = s;
uint[] storage y = s;
}
//只要是storage赋值storage或memory赋值memory都是引用赋值
function test_storage() internal {
ref_internal(ref_a); //storage赋值storage是引用赋值,相互改变!
}
//只要是memory赋值storage或storage赋值memory都是拷贝赋值
function test_memory() private {
ref_private(ref_a); //storage赋值memory是拷贝赋值,相互不影响!
}
// private类型函数的函数参数引用类型必须是storage或memory
function ref_private(uint[] memory s) private {
s[0] = 2019;
}
// internal类型函数的函数参数引用类型必须是storage或memory
function ref_internal(uint[] storage s) internal {
s[0] = 2019;
}
// public类型函数的函数参数引用类型只能是memory
function ref_public(uint[] memory s) public {
s[0] = 2019;
}
// external类型函数的函数参数引用类型只能是calldata
function ref_external(uint[] calldata s) external {
//这里无法修改s的值!!!
}
}
关于状态变量之间的storage数组直接的拷贝赋值!
pragma solidity ^0.5.0;
contract Test {
// 全局复杂引用变量默认都是storage(存于区块链中,永久存在)
uint[] public ref_a = [1,2,3];
// new关键字创建的storage类型的数组(注意:new既可以创建memory数组也可以创建storage数组)
uint[] public ref_b = new uint[](8);
function chang_array() public returns(uint){
// ref_b和ref_a都是状态变量,状态变量之间的赋值完全独立拷贝!(切记)
ref_b = ref_a;
ref_b[0] = 10;
}