【CryptoZombies - 1 Solidity 教程】013 永久存储变量(storage)和 临时存储变量(memory)

本文主要是介绍【CryptoZombies - 1 Solidity 教程】013 永久存储变量(storage)和 临时存储变量(memory),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、前言

看了一些区块链的教程,论文,在网上刚刚找到了一个项目实战,CryptoZombies。

如果你想了解更多有关于机器学习、深度学习、区块链、计算机视觉等相关技术的内容,想与更多大佬一起沟通,那就扫描下方二维码加入我们吧!

二、 永久存储变量(Storage)和 临时存储变量(Memory)

1、讲解

我们在代码中会经常需要存储变量,有些变量是我们永久存储的,有些则是临时存储的,在solidity中,也是如此。solidity有两种存储变量:

1.storage 变量是永久存储在区块链中的变量

2.memory 变量是临时存储在区块链中的变量,当外部函数对某合约调用完成时,内存型变量即被移除。

当然,大多数情况下,我们很少会用到,solidity会自动处理,状态变量(在函数外声明的变量)默认为storage类型的变量,即永久存储,状态变量会永久写入区块链。在函数内部声明的变量,是memory类型的变量,函数调用结束就会消失。

除了系统默认之外,我们也可以自己手动声明,一般常用于我们处理函数内部的结构体structs和数组arrays

例如下面的示例。

contract SandwichFactory {struct Sandwich {string name;string status;}Sandwich[] sandwiches;function eatSandwich(uint _index) public {// Sandwich mySandwich = sandwiches[_index];}
}

上面添加注释的这句话,看上去很直接,不过 Solidity 会给出警告 ,应该明确在这里定义 `storage` 或者 `memory`。 正确写法如下:

contract SandwichFactory {struct Sandwich {string name;string status;}Sandwich[] sandwiches;function eatSandwich(uint _index) public {// Sandwich mySandwich = sandwiches[_index];Sandwich storage mySandwich = sandwiches[_index];mySandwich.status = "Eaten!";}
}

其中 `mySandwich` 是指向 `sandwiches[_index]`的指针 ,这将永久把 `sandwiches[_index]` 变为区块链上的存储。

如果你只想要一个副本,可以这样写:

contract SandwichFactory {struct Sandwich {string name;string status;}Sandwich[] sandwiches;function eatSandwich(uint _index) public {Sandwich memory anotherSandwich = sandwiches[_index + 1];anotherSandwich.status = "Eaten!";}
}

这样 `anotherSandwich` 就仅仅是一个内存里的副本了 ,后续操作也仅仅修改临时变量,对 `sandwiches[_index + 1]` 没有任何影响。

如果想把副本的改动保存回区块链存储,可以这样做:

contract SandwichFactory {struct Sandwich {string name;string status;}Sandwich[] sandwiches;function eatSandwich(uint _index) public {Sandwich memory anotherSandwich = sandwiches[_index + 1];anotherSandwich.status = "Eaten!";sandwiches[_index + 1] = anotherSandwich;}
}

所以我们在具体使用过程中,也需要考虑使用storge还是memory。

2、实战1

1.要求

当一个僵尸猎食其他生物体时,它自身的DNA将与猎物生物的DNA结合在一起,形成一个新的僵尸DNA。

1.创建一个名为 feedAndMultiply 的函数。 使用两个参数:_zombieId( uint类型 )和_targetDna (也是 uint 类型)。设置属性为 public 的。

2.我们不希望别人用我们的僵尸去捕猎。 首先,我们确保对自己僵尸的所有权。 通过添加一个require 语句来确保 msg.sender 只能是这个僵尸的主人(类似于我们在 createRandomZombie 函数中做过的那样)。

3.为了获取这个僵尸的DNA,我们的函数需要声明一个名为 myZombie 数据类型为Zombie的本地变量(这是一个 storage 型的指针)。 将其值设定为在 zombies 数组中索引为_zombieId所指向的值。

到目前为止,包括函数结束符 } 的那一行, 总共4行代码。

2.代码

pragma solidity >=0.5.0 <0.6.0;import "./zombiefactory.sol";contract ZombieFeeding is ZombieFactory {// Start herefunction feedAndMultiply(uint _zombieId, uint _targetDna) public {require(msg.sender == zombieToOwner[_zombieId]);Zombie storage myZombie = zombies[_zombieId];}}

 

3、实战2

1.要求

1.首先确保 _targetDna 不长于16位。要做到这一点,设置 _targetDna 为 _targetDna % dnaModulus ,并且只取其最后16位数字。

2.接下来为函数声明一个名叫 newDna 的 uint类型的变量,并将其值设置为 myZombie的 DNA 和 _targetDna 的平均值(如上例所示)。

注意:可以用 myZombie.name 或 myZombie.dna 访问 myZombie 的属性

3.一旦计算出新的DNA,再调用 _createZombie 就可以生成新的僵尸了。如果忘记调用这个函数所需要的参数,可以查看 zombiefactory.sol 选项卡。请注意,需要先给它命名,把新的僵尸的名字设为NoName - 也可以编写一个函数来更改僵尸的名字。

2.代码

pragma solidity >=0.5.0 <0.6.0;import "./zombiefactory.sol";contract ZombieFeeding is ZombieFactory {function feedAndMultiply(uint _zombieId, uint _targetDna) public {require(msg.sender == zombieToOwner[_zombieId]);Zombie storage myZombie = zombies[_zombieId];// start here_targetDna = _targetDna%dnaModulus;uint newDna = (myZombie.dna + _targetDna) / 2;_createZombie("NoName", newDna);}}

这篇关于【CryptoZombies - 1 Solidity 教程】013 永久存储变量(storage)和 临时存储变量(memory)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/482040

相关文章

Python中Tkinter GUI编程详细教程

《Python中TkinterGUI编程详细教程》Tkinter作为Python编程语言中构建GUI的一个重要组件,其教程对于任何希望将Python应用到实际编程中的开发者来说都是宝贵的资源,这篇文... 目录前言1. Tkinter 简介2. 第一个 Tkinter 程序3. 窗口和基础组件3.1 创建窗

Java 接口定义变量的示例代码

《Java接口定义变量的示例代码》文章介绍了Java接口中的变量和方法,接口中的变量必须是publicstaticfinal的,用于定义常量,而方法默认是publicabstract的,必须由实现类... 在 Java 中,接口是一种抽象类型,用于定义类必须实现的方法。接口可以包含常量和方法,但不能包含实例

Python中Request的安装以及简单的使用方法图文教程

《Python中Request的安装以及简单的使用方法图文教程》python里的request库经常被用于进行网络爬虫,想要学习网络爬虫的同学必须得安装request这个第三方库,:本文主要介绍P... 目录1.Requests 安装cmd 窗口安装为pycharm安装在pycharm设置中为项目安装req

JavaWeb项目创建、部署、连接数据库保姆级教程(tomcat)

《JavaWeb项目创建、部署、连接数据库保姆级教程(tomcat)》:本文主要介绍如何在IntelliJIDEA2020.1中创建和部署一个JavaWeb项目,包括创建项目、配置Tomcat服务... 目录简介:一、创建项目二、tomcat部署1、将tomcat解压在一个自己找得到路径2、在idea中添加

详解C++ 存储二进制数据容器的几种方法

《详解C++存储二进制数据容器的几种方法》本文主要介绍了详解C++存储二进制数据容器,包括std::vector、std::array、std::string、std::bitset和std::ve... 目录1.std::vector<uint8_t>(最常用)特点:适用场景:示例:2.std::arra

解决idea启动项目报错java: OutOfMemoryError: insufficient memory

《解决idea启动项目报错java:OutOfMemoryError:insufficientmemory》:本文主要介绍解决idea启动项目报错java:OutOfMemoryError... 目录原因:解决:总结 原因:在Java中遇到OutOfMemoryError: insufficient me

Python + Streamlit项目部署方案超详细教程(非Docker版)

《Python+Streamlit项目部署方案超详细教程(非Docker版)》Streamlit是一款强大的Python框架,专为机器学习及数据可视化打造,:本文主要介绍Python+St... 目录一、针对 Alibaba Cloud linux/Centos 系统的完整部署方案1. 服务器基础配置(阿里

Spring IOC核心原理详解与运用实战教程

《SpringIOC核心原理详解与运用实战教程》本文详细解析了SpringIOC容器的核心原理,包括BeanFactory体系、依赖注入机制、循环依赖解决和三级缓存机制,同时,介绍了SpringBo... 目录1. Spring IOC核心原理深度解析1.1 BeanFactory体系与内部结构1.1.1

SpringBoot集成iText快速生成PDF教程

《SpringBoot集成iText快速生成PDF教程》本文介绍了如何在SpringBoot项目中集成iText9.4.0生成PDF文档,包括新特性的介绍、环境准备、Service层实现、Contro... 目录SpringBoot集成iText 9.4.0生成PDF一、iText 9新特性与架构变革二、环

2025最新版Android Studio安装及组件配置教程(SDK、JDK、Gradle)

《2025最新版AndroidStudio安装及组件配置教程(SDK、JDK、Gradle)》:本文主要介绍2025最新版AndroidStudio安装及组件配置(SDK、JDK、Gradle... 目录原生 android 简介Android Studio必备组件一、Android Studio安装二、A