涉及 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);
}
}