阅读(3451) (15)

任务

2022-05-12 15:15:02 更新

解构赋值并返回多个值

Solidity 内部允许元组类型,即可能不同类型的对象列表,其编号在编译时是一个常数。这些元组可用于同时返回多个值。然后可以将它们分配给新声明的变量或预先存在的变量(或一般的 LValues)。

元组在 Solidity 中不是正确的类型,它们只能用于形成表达式的句法分组。

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.9.0;

contract C {
    uint index;

    function f() public pure returns (uint, bool, uint) {
        return (7, true, 2);
    }

    function g() public {
        // Variables declared with type and assigned from the returned tuple,
        // not all elements have to be specified (but the number must match).
        (uint x, , uint y) = f();
        // Common trick to swap values -- does not work for non-value storage types.
        (x, y) = (y, x);
        // Components can be left out (also for variable declarations).
        (index, , ) = f(); // Sets the index to 7
    }
}

不能混合变量声明和非声明赋值,即以下内容无效:(x, uint y) = (1, 2);

笔记

在 0.5.0 版本之前,可以分配给较小尺寸的元组,或者填充在左侧或右侧(曾经是空的)。现在不允许这样做,因此双方必须具有相同数量的组件。

警告

在涉及引用类型时同时分配多个变量时要小心,因为它可能导致意外的复制行为。

数组和结构的复杂性

对于数组和结构等非值类型,包括bytesand string,赋值的语义更为复杂,有关详细信息,请参阅数据位置和赋值行为

在下面的示例中,调用对g(x)on 没有影响,x因为它在内存中创建了存储值的独立副本。但是,h(x)成功修改,x 因为只传递了一个引用而不是一个副本。

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.22 <0.9.0;

contract C {
    uint[20] x;

    function f() public {
        g(x);
        h(x);
    }

    function g(uint[20] memory y) internal pure {
        y[2] = 3;
    }

    function h(uint[20] storage y) internal {
        y[3] = 4;
    }
}