涉及 LValues 的运算符¶
如果 a
是一个 LValue(即一个变量或者其它可以被赋值的东西),以下运算符都可以使用简写:
a += e
等同于 a = a + e
。 其它运算符 -=
, *=
, /=
, %=
, |=
, &=
以及 ^=
都是如此定义的。
a++
和 a--
分别等同于 a += 1
和 a -= 1
,但表达式本身的值等于 a
在计算之前的值。
与之相反,--a
和 ++a
虽然最终 a
的结果与之前的表达式相同,但表达式的返回值是计算之后的值。
delete¶
delete a
的结果是将a
类型初始值赋值给a
。即对于整型变量来说,相当于a = 0
,delete 也适用于数组,对于动态数组来说,是将重置为数组长度为0的数组,而对于静态数组来说,是将数组中的所有元素重置为初始值。 对数组而言,
delete a[x]
仅删除数组索引x
处的元素,其他的元素和长度不变,这以为着数组中留出了一个空位。如果打算删除项,映射可能是更好的选择。
如果对象 a
是结构体,则将结构体中的所有属性(成员)重置。
换句话说,在 delete a
之后 a
的值与在没有赋值的情况下声明 a
的情况相同,
但需要注意以下几点:
delete
对整个映射是无效的(因为映射的键可以是任意的,通常也是未知的)。
因此在你删除一个结构体时,结果将重置所有的非映射属性(成员),这个过程是递归进行的,除非它们是映射。
然而,单个的键及其映射的值是可以被删除的。
理解 delete a
的效果就像是给 a
赋值很重要,换句话说,这相当于在 a
中存储了一个新的对象。
当 a
是应用变量时,我们可以看到这个区别,delete a
它只会重置 a
本身,而不是更改它之前引用的值。
pragma solidity >=0.4.0 <0.7.0;
contract DeleteLBC {
uint data;
uint[] dataArray;
function f() public {
uint x = data;
delete x; // 将 x 设为 0,并不影响数据
delete data; // 将 data 设为 0,并不影响 x,因为它仍然有个副本
uint[] storage y = dataArray;
delete dataArray;
// 将 dataArray.length 设为 0,但由于 uint[] 是一个复杂的对象,y 也将受到影响,
// 因为它是一个存储位置是 storage 的对象的别名。
// 另一方面:"delete y" 是非法的,引用了 storage 对象的局部变量只能由已有的 storage 对象赋值。
assert(y.length == 0);
}
}