智能合约语言 Solidity 教程系列4 - 数据存储位置分析
最新内容会更新在主站深入浅出区块链社区
原文链接:智能合约语言 Solidity 教程系列4 - 数据存储位置分析
写在前面
Solidity 是以太坊智能合约编程语言,阅读本文前,你应该对以太坊、智能合约有所了解,
如果你还不了解,建议你先看以太坊是什么
这部分的内容官方英文文档讲的不是很透,因此我在参考Solidity官方文档(当前最新版本:0.4.20)的同时加入了深入分析部分,欢迎订阅专栏。
数据位置(Data location)
在系列第一篇,我们提到 Solidity 类型分为两类:
值类型(Value Type) 及 引用类型(Reference Types),
前面我们已经介绍完了值类型,接下来会介绍引用类型。
引用类型是一个复杂类型,占用的空间通常超过256位, 拷贝时开销很大,因此我们需要考虑将它们存储在什么位置,是memory(内存中,数据不是永久存在)还是storage(永久存储在区块链中)
所有的复杂类型如数组(arrays)和数据结构(struct)有一个额外的属性:数据的存储位置(data location)。可为memory和storage。
根据上下文的不同,大多数时候数据位置有默认值,也通过指定关键字storage和memory修改它。
函数参数(包含返回的参数)默认是memory。
局部复杂类型变量(local variables)和 状态变量(state variables) 默认是storage。
局部变量:局部作用域(越过作用域即不可被访问,等待被回收)的变量,如函数内的变量。状态变量:合约内声明的公有变量
还有一个存储位置是:calldata,用来存储函数参数,是只读的,不会永久存储的一个数据位置。外部函数的参数(不包括返回参数)被强制指定为calldata。效果与memory差不多。
数据位置指定非常重要,因为他们影响着赋值行为。
在memory和storage之间或与状态变量之间相互赋值,总是会创建一个完全独立的拷贝。
而将一个storage的状态变量,赋值给一个storage的局部变量,是通过引用传递。所以对于局部变量的修改,同时修改关联的状态变量。
另一方面,将一个memory的引用类型赋值给另一个memory的引用,不会创建拷贝(即:memory之间是引用传递)。
- 注意:不能将memory赋值给局部变量。
- 对于值类型,总是会进行拷贝。
下面看一段代码:
pragma solidity ^0.4.0;
contract C {
uint[] x; // x的存储位置是storage
// memoryArray的存储位置是 memory
function f(uint[] memoryArray) public {
x = memoryArray; // 从 memory 复制到 storage
var y = x; // storage 引用传递局部变量y(y 是一个 storage 引用)
y[7]; // 返回第8个元素
y.length = 2; // x同样会被修改
delete x; // y同样会被修改
// 错误, 不能将memory赋值给局部变量
// y = memoryArray;
// 错误,不能通过引用销毁storage
// delete y;
g(x); // 引用传递, g可以改变x的内容
h(x); // 拷贝到memory, h无法改变x的内容
}
function g(uint[] storage storageArray) internal {}
function h(uint[] memoryArray) public {}
}
总结
强制的数据位置(Forced data location)
- 外部函数(External function)的参数(不包括返回参数)强制为:calldata
- 状态变量(State variables)强制为: storage
默认数据位置(Default data location)
- 函数参数及返回参数:memory
- 复杂类型的局部变量:storage
深入分析
storage 存储结构是在合约创建的时候就确定好了的,它取决于合约所声明状态变量。但是内容可以被(交易)调用改变。
Solidity 称这个为状态改变,这也是合约级变量称为状态变量的原因。也可以更好的理解为什么状态变量都是storage存储。
memory 只能用于函数内部,memory 声明用来告知EVM在运行时创建一块(固定大小)内存区域给变量使用。
storage 在区块链中是用key/value的形式存储,而memory则表现为字节数组
关于栈(stack)
EVM是一个基于栈的语言,栈实际是在内存(memory)的一个数据结构,每个栈元素占为256位,栈最大长度为1024。
值类型的局部变量是存储在栈上。
不同存储的消耗(gas消耗)
- storage 会永久保存合约状态变量,开销最大
- memory 仅保存临时变量,函数调用之后释放,开销很小
- stack 保存很小的局部变量,几乎免费使用,但有数量限制。
参考视频
我们也推出了目前市面上最全的视频教程:深入详解以太坊智能合约语言Solidity
目前我们也在招募体验师,可以点击链接了解。
参考资料
深入浅出区块链 - 系统学习区块链,打造最好的区块链技术博客
智能合约语言 Solidity 教程系列4 - 数据存储位置分析的更多相关文章
- 智能合约语言Solidity教程系列2 - 地址类型介绍
智能合约语言Solidity教程系列第二篇 - Solidity地址类型介绍. 写在前面 Solidity是以太坊智能合约编程语言,阅读本文前,你应该对以太坊.智能合约有所了解,如果你还不了解,建议你 ...
- 智能合约语言 Solidity 教程系列6 - 结构体与映射
写在前面 Solidity 是以太坊智能合约编程语言,阅读本文前,你应该对以太坊.智能合约有所了解, 如果你还不了解,建议你先看以太坊是什么 本系列文章一部分是参考Solidity官方文档(当前最新版 ...
- 智能合约语言 Solidity 教程系列5 - 数组介绍
写在前面 Solidity 是以太坊智能合约编程语言,阅读本文前,你应该对以太坊.智能合约有所了解, 如果你还不了解,建议你先看以太坊是什么 本文前半部分是参考Solidity官方文档(当前最新版本: ...
- 智能合约语言 Solidity 教程系列8 - Solidity API
这是Solidity教程系列文章第8篇介绍Solidity API,它们主要表现为内置的特殊的变量及函数,存在于全局命名空间里. 写在前面 Solidity 是以太坊智能合约编程语言,阅读本文前,你应 ...
- 智能合约语言 Solidity 教程系列3 - 函数类型
Solidity 教程系列第三篇 - Solidity 函数类型介绍. 写在前面 Solidity 是以太坊智能合约编程语言,阅读本文前,你应该对以太坊.智能合约有所了解,如果你还不了解,建议你先看以 ...
- 智能合约语言 Solidity 教程系列9 - 错误处理
这是Solidity教程系列文章第9篇介绍Solidity 错误处理. Solidity系列完整的文章列表请查看分类-Solidity. 写在前面 Solidity 是以太坊智能合约编程语言,阅读本文 ...
- 智能合约语言 Solidity 教程系列10 - 完全理解函数修改器
这是Solidity教程系列文章第10篇,带大家完全理解Solidity的函数修改器. Solidity系列完整的文章列表请查看分类-Solidity. 写在前面 Solidity 是以太坊智能合约编 ...
- 智能合约语言 Solidity 教程系列7 - 以太单位及时间单位
这是Solidity教程系列文章第7篇介绍以太单位及时间单位,系列带你全面深入理解Solidity语言. 写在前面 Solidity 是以太坊智能合约编程语言,阅读本文前,你应该对以太坊.智能合约有所 ...
- 智能合约语言 Solidity 教程系列2 - 地址类型介绍
Solidity教程系列第二篇 - Solidity地址类型介绍. 写在前面 Solidity是以太坊智能合约编程语言,阅读本文前,你应该对以太坊.智能合约有所了解,如果你还不了解,建议你先看以太坊是 ...
随机推荐
- A计划(双层bfs)
A计划 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submissio ...
- .NET Core跨平台的奥秘[上篇]:历史的枷锁
微软推出的第一个版本的.NET Framework是一个面向Windows桌面和服务器的基础框架,在此之后,为此微软根据设备自身的需求对.NET Framework进行裁剪,不断推出了针对具体设备类型 ...
- Node.js Web 模块
什么是 Web 服务器? Web服务器一般指网站服务器,是指驻留于因特网上某种类型计算机的程序,Web服务器的基本功能就是提供Web信息浏览服务.它只需支持HTTP协议.HTML文档格式及URL,与客 ...
- css元素选择器 first-child nth-child
E:first-child 只要E元素是它的父级的第一个子元素,就选中.它需要同时满足两个条件, (1)是"第一个子元素", (2)是"这个子元素刚好是E ...
- JAVA爬虫代码
工程目录: 所需要的jar包为: jsoup-1.10.2.jar /** * Created by wangzheng on 2017/2/19. */ public class Article ...
- php 常用 常量集合
DIRECTORY_SEPARATOR 常量 DIRECTORY_SEPARATOR 目录分割符
- DateTime格式
SELECT * FROM TABLE (TO_DATE('2007/9/1','yyyy/mm/dd') BETWEEN CGGC_STRATDATE AND CGGC_ENDDATE OR CGG ...
- 结合java.util.TreeMap源码理解红黑树
前言 本篇将结合JDK1.6的TreeMap源码,来一起探索红-黑树的奥秘.红黑树是解决二叉搜索树的非平衡问题. 当插入(或者删除)一个新节点时,为了使树保持平衡,必须遵循一定的规则,这个规则就是红- ...
- FPGA调试光纤模块
利用FPGA调试光纤接口接口: 由于与项目需要,前段时间调试了光纤接口,记录一些设计经验. 设计中采用FPGA控制光纤模块完成光纤数据的收发,FPGA采用Xilinx公司的Spartan6 LX45T ...
- 移动端h5拍照压缩即时上传后台并预览
项目经理让迭代一个功能,实时预览并上传到后台的功能,听到这立马想起了几个第三方插件去实现,mui 和api cloude万万没想到的是这个app前面使用ios 和安卓原生写的,然后mui和api c ...