引用类型在Solidity中有一个额外的属性,数据的存储位置。可选为memory和storage。
memory
:存储位置同我们普通程序的内存一致。即分配,即使用,越过作用域即不可被访问,等待被回收。
storage
:这种类型了,一旦使用这个类型,数据将永远存在。
calldata
:它存储的是函数参数,是只读的,不会永久存储的一个数据位置。外部函数的参数(不包括返回参数)被强制指定为calldata。效果与memory差不多。
外部函数
(External function)的参数(不包括返回参数)强制为:calldata
状态变量
:强制为: storage
pragma solidity ^0.4.0;
contract StateVariable{
struct S{string a;uint b;}
//状态变量,默认是storage
S s;
}
函数参数
,返回参数
:memory
局部变量
:storage
pragma solidity ^0.4.0;
contract SimpleAssign{
struct S{string a;uint b;}
function assign(S s) internal{ //默认参数是memory
//默认的变量是storage的指针
//S tmp = s; 报错
}
}
这里将一个memory类型的参数赋值给storage类型的局部变量会报错
1.storage–>storage
把一个storage类型赋值给一个storage类型时,只是修改其指针(引用传递)
pragma solidity ^0.4.0;
contract StorageToStorageTest{
struct S{string a;uint b;}
//默认是storage的
S s;
function storageTest(S storage s) internal{
S test = s;
test.a = "Test";
}
function call() returns (string){
storageTest(s);
return s.a;//Test
}
}
2.memory–>storage
分为2种情况:
a.将memory–>状态变量;即将内存中的变量拷贝到存储中(值传递)
pragma solidity ^0.4.0;
contract StorageToStorageTest{
struct S{string a;uint b;}
//默认是storage的
S s;
function storageTest(S s) internal{
s = s;
s.a = "Test";
}
function call() returns (string){
storageTest(s);
return s.a;//
}
}
b.将memeory–>局部变量 报错
3.storage–>memory:即将数据从storage拷贝到memory中
pragma solidity ^0.4.0;
contract StorageToMemory{
struct S{string a;uint b;}
S s = S("storage", 1);
function storageToMemory(S storage x) internal{
S memory tmp = x;//由Storage拷贝到memory中
//memory的修改不影响storage
tmp.a = "Test";
}
function call() returns (string){
storageToMemory(s);
return s.a;//storage
}
}
4.memory–>memory 和storage转storage一样是引用传递
pragma solidity ^0.4.0;
contract MemoryToMemory{
struct S{string a;uint b;}
function smemoryTest(S s) internal{
S memory test = s;
test.a = "Test";
}
function call() returns (string){
//默认是storage的
S memory s = S("memory",10);
smemoryTest(s);
return s.a;//Test
}
}