本课介绍了数组和结构体的定义和用法
数组可以在声明时指定长度,也可以动态调整大小。 一个元素类型为 T,固定长度为 k 的数组可以声明为 T[k], 而动态数组声明为 T[]。
- 特点:
- 访问一个超过它的末端的数组会导致一个失败的断言。方法 .push() 和 .push(value) 可以用来在动态大小的数组末端追加一个新的元素, 其中 .push() 追加一个零初始化的元素并返回它的引用。
- bytes 和 string 类型的变量是特殊的数组。但不允许用长度或索引来访问。
- 不可能调整内存数组的大小,必须事先计算出所需的大小,或者创建一个新的内存数组并复制每个元素。
- 要在外部(而不是公开)函数中使用数组的数组, 需要激活ABI coder v2。
- 数组成员
- length: 数组有一个包含元素数量的length成员,memory数组的长度在创建后是固定的。
- push(): 动态数组拥有push()成员,可以在数组最后添加一个0元素,并返回该元素的引用。
- push(x): 动态数组拥有push(x)成员,可以在数组最后添加一个x元素。
- pop(): 动态数组拥有pop()成员,可以移除数组最后一个元素。
Solidity支持通过构造结构体的形式定义新的类型。结构体中的元素可以是原始类型,也可以是引用类型;结构体可以作为数组或映射的元素。 给结构体赋值的四种方法
- 在函数中创建一个storage的struct引用
function initStudent1() external{
Student storage _student = student; // assign a copy of student
_student.id = 11;
_student.score = 100;
}
- 直接引用状态变量的struct
function initStudent2() external{
student.id = 1;
student.score = 80;
}
- 构造函数赋值
function initStudent3() external {
student = Student(3, 90);
}
- key-value赋值
function initStudent4() external {
student = Student({id: 4, score: 60});
}
注意:结构体不可能包含其自身类型的成员,尽管结构本身可以是映射成员的值类型, 或者可以包含其本身类型的动态大小的数组。
Solidity中存储键值对的数据结构,可以理解为哈希表。 声明映射的格式为mapping(_KeyType => _ValueType),其中_KeyType和_ValueType分别是Key和Value的变量类型。
- 映射的_KeyType只能选择Solidity内置的值类型,不能用自定义的结构体。
- 不能用于public函数的参数或返回结果中,因为mapping记录的是一种关系 (key - value pair)。
- 如果映射声明为public,那么Solidity会自动给你创建一个getter函数,可以通过Key来查询对应的Value。
- 给映射新增的键值对的语法为_Var[_Key] = _Value,其中_Var是映射变量名,_Key和_Value对应新增的键值对。
function writeMap (uint _Key, address _Value) public{
idToAddress[_Key] = _Value;
}
- 映射不储存任何键(Key)的资讯,也没有length。
- 映射使用keccak256(abi.encode(key, slot))当成offset存取value,其中slot是映射变量定义所在的插槽位置。
- 因为Ethereum会定义所有未使用的空间为0,所以未赋值(Value)的键(Key)初始值都是各个type的默认值,如uint的默认值是0。
在Solidity中,声明但没赋值的变量都有它的初始值或默认值。
- boolean: false
- string: ""
- int: 0
- uint: 0
- enum: 枚举中的第一个元素的值
- address: 0x0000000000000000000000000000000000000000 (或 address(0))
- function
- internal: 空白函数
- external: 空白函数
- 映射mapping: 所有元素都为其默认值的mapping
- 结构体struct: 所有成员设为其默认值的结构体
- 数组array
- 动态数组: []
- 静态数组(定长): 所有成员设为其默认值的静态数组
delete会把一个变量的值设置为初始值
bool public _bool2 = true;
function d() external {
delete _bool2; // delete 会让_bool2变为默认值,false
}
我们介绍Solidity中和常量相关的两个关键字,constant(常量)和immutable(不变量)。状态变量声明这两个关键字之后,不能在初始化后更改数值。这样做的好处是提升合约的安全性并节省gas。
注意: 只有数值变量可以声明constant和immutable;string和bytes可以声明为constant,但不能为immutable。
- constant变量必须在声明的时候初始化。
- immutable变量可以在声明时或构造函数中初始化若,immutable变量既在声明时初始化,又在constructor中初始化,会使用constructor初始化的值。