了解引用类型

在编写合同时,还应了解引用类型。

与总是传递值的独立副本的值类型不同,引用类型为值提供数据位置。 这三种引用类型为:结构、数组和映射。

数据位置

使用引用类型时,必须显式提供该类型的数据存储位置。 以下选项可用于指定存储类型的数据位置:

  • memory
    • 存储函数参数的位置
    • 生存期限制为外部函数调用的生存期
  • storage
    • 存储状态变量的位置
    • 生存期仅限于合同生存期
  • calldata
    • 存储函数参数的位置
    • 此位置对于外部函数的参数是必需的,但也可用于其他变量
    • 生存期限制为外部函数调用的生存期

引用类型总是创建数据的独立副本。

下面举例说明如何使用引用类型:

contract C {

  uint[] x;
  
  // the data location of values is memory
  function buy(uint[] memory values) public {
      x = values; // copies array to storage
      uint[] storage y = x; //data location of y is storage
      g(x); // calls g, handing over reference to x
      h(x); // calls h, and creates a temporary copy in memory
  }

  function g(uint[] storage) internal pure {}
  function h(uint[] memory) public pure {}
}

数组

数组是一种在集合数据结构中存储相似数据的方法。 数组可以是固定大小,也可以是动态大小。 它们的索引从 0 开始。

若要创建固定大小的 k 和元素类型 T 的数组,则需要编写 T[k]。 对于动态大小数组,应编写 T[]

数组元素可以是任何类型。 例如,它们可以包含“uint”、“memory”或“bytes”。 数组还可以包括“映射”或“结构”。

以下示例演示如何创建数组:

uint[] itemIds; // Declare a dynamically sized array called itemIds
uint[3] prices = [1, 2, 3]; // initialize a fixed size array called prices, with prices 1, 2, and 3
uint[] prices = [1, 2, 3]; // same as above

数组成员

以下成员既可以操作数组,又可以获取有关数组的信息:

  • length:获取数组的长度。
  • push():在数组末尾追加一个元素。
  • pop:从数组末尾删除元素。

下面是一些示例:

// Create a dynamic byte array
bytes32[] itemNames;
itemNames.push(bytes32("computer")); // adds "computer" to the array
itemNames.length; // 1

结构

结构是用户可以定义用来表示实际界对象的自定义类型。 结构通常用作架构或用于表示记录。

结构声明示例:

struct Items_Schema {
    uint256 _id;
    uint256 _price;
    string _name;
    string _description;
}

映射类型

映射是封装或打包在一起的键值对。 映射最接近 JavaScript 中的字典或对象。 通常使用映射来建模实际对象,并执行快速数据查找。 这些值可以包括结构等复杂类型,这使得映射类型灵活且可读性强。

下面的代码示例使用结构 Items_Schema,并将 Items_Schema 表示的项列表保存为字典。 映射通过这种方式模拟数据库。

// 定义一个名为 Items 的智能合约
contract Items {
    // 定义一个状态变量 item_id,类型为 uint256,用于跟踪下一个项目的 ID。
    uint256 item_id = 0;

    // 定义一个映射,键为 uint256 类型的项目 ID,值为 Items_Schema 结构体类型的项目。
    // 这个映射允许我们通过项目 ID 查找项目数据。
    mapping(uint256 => Items_Schema) public items;

    // 定义一个结构体 Items_Schema,用于表示项目的属性。
    // 注意:Solidity 中结构体成员的定义不需要分号。
    struct Items_Schema {
        // 定义项目 ID,类型为 uint256。
        uint256 _id;
        // 定义项目价格,类型为 uint256。
        uint256 _price;
        // 定义项目名称,类型为 string。
        string _name;
    }

    // 定义一个公共函数 listItem,用于向映射中添加一个新的项目。
    // 函数接收项目的价格(_price)和名称(_name)作为参数。
    function listItem(uint256 memory _price, string memory _name) public {
        // 创建一个新的 Items_Schema 实例,并将其添加到映射 items 中。
        // 使用当前的 item_id 作为键。
        // 注意:这里使用了结构体的构造器语法,但 Solidity 0.6.0 及更高版本中推荐使用结构体字面量语法。
        //items[item_id] = Items_Schema({
        //_id: item_id,
        //_price: _price,
        //_name: _name
        //});
        items[item_id] = Items_Schema(item_id, _price, _name);

        // 增加 item_id 的值,准备为下一个项目分配新的 ID。
        item_id += 1;
    }
}

 备注:

映射签名 uint256 => Items_Schema 表示键是无符号整数类型,值是 Items_Schema 结构类型。

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值