Solidity中有两种类型:值类型和引用类型
Solidity是静态类型的语言,有值类型和引用类型的区别。
如果一个变量是值类型,那么当把它的值传给另一个变量时,是复制值,对新变量的操作不会影响原来的变量;如果该变量是引用类型,那么当它传值给另一个变量时,则是把该值的地址复制给新的变量。这样操作新变量也会导致旧变量的改变。
值类型:
布尔类型(bool)、整型(int)、地址类型(address)、定长字节数组(bytes)、枚举类型(enums)、函数类型(function);
如果一个变量是值类型,给它赋值时永远是值传递!
引用类型:
字符串(string)、数组(array)、结构体(structs)、字典(mapping)、不定长字节数组(bytes)
如果一个变量是引用类型,给它赋值时可以是值,也可以是引用,这决定于该变量是Storage类型还是Memory类型。
关键字:Storage 和 Memory
Storage 是把变量永久储存在区块链中,Memory 则是把变量临时放在内存中,当外部函数对某合约调用完成时,内存型变量即被移除。 你可以把它想象成存储在你电脑的硬盘或是RAM中数据的关系。
大多数时候你都用不到这些关键字,默认情况下 Solidity 会自动处理它们。
状态变量(在函数之外声明的变量)默认为“存储”形式,并永久写入区块链;而在函数内部声明的变量是“内存”型的,它们函数调用结束后消失。
通过指定引用类型变量的关键字,可以人为设置变量为storage或memory。
函数的引用类型参数是storage时,是引用传递;函数的引用类型参数是Memory时,是值传递;函数值类型参数永远是值传递。
扫描二维码关注公众号,回复:
3667793 查看本文章
contract example {
uint _a; // 状态变量_a,值类型变量,不存在memory的定位,就是存在区块链中的
string _b; // 状态变量_b,引用类型变量,默认storage
function example1 (string b1){
_b = b1; // 参数默认是Memory型变量,进行值传递
}
function example2 (string storage b2) private/internal {
_b = b2; // 参数默认是Memory型变量,进行值传递;但是这里设定为storage,就是进行引用传递了
// 参数是storage类型时,函数必须是private或internal类型的
}
function example3 (uint storage/memory a) {
_a = a; // error: storage location can only be given for Array or String type
}
}
有一个很好的例子:
contract SandwichFactory {
struct Sandwich {
string name;
string status;
}
Sandwich[] sandwiches;
function eatSandwich(uint _index) public {
// Sandwich mySandwich = sandwiches[_index];
/*
看上去很直接,不过 Solidity 将会给出警告,告诉你应该明确在这里定义 `storage` 或者 `memory`。
所以你应该明确定义 `storage`:
*/
Sandwich storage mySandwich = sandwiches[_index];
// 这样 `mySandwich` 是指向 `sandwiches[_index]`的指针在存储里,另外...
mySandwich.status = "Eaten!";
// 这将永久把 `sandwiches[_index]` 变为区块链上的存储,如果你只想要一个副本,可以使用`memory`:
Sandwich memory anotherSandwich = sandwiches[_index + 1];
// 这样 `anotherSandwich` 就仅仅是一个内存里的副本了
// 另外
anotherSandwich.status = "Eaten!";
// 将仅仅修改临时变量,对 `sandwiches[_index + 1]` 没有任何影响
// 不过你可以这样做:
sandwiches[_index + 1] = anotherSandwich;
// 如果你想把副本的改动保存回区块链存储
}
}