本文首发于深刻浅出区块链社区 原文连接:智能合约语言 Solidity 教程系列4 - 数据存储位置分析原文已更新,请读者前往原文阅读html
Solidity 是以太坊智能合约编程语言,阅读本文前,你应该对以太坊、智能合约有所了解, 若是你还不了解,建议你先看以太坊是什么编程
这部分的内容官方英文文档讲的不是很透,所以我在参考Solidity官方文档(当前最新版本:0.4.20)的同时加入了深刻分析部分,欢迎订阅专栏。数组
在系列第一篇,咱们提到 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差很少。ui
数据位置指定很是重要,由于他们影响着赋值行为。 在memory和storage之间或与状态变量之间相互赋值,老是会建立一个彻底独立的拷贝。 而将一个storage的状态变量,赋值给一个storage的局部变量,是经过引用传递。因此对于局部变量的修改,同时修改关联的状态变量。 另外一方面,将一个memory的引用类型赋值给另外一个memory的引用,不会建立拷贝(即:memory之间是引用传递)。code
- 注意:不能将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 {} }
storage 存储结构是在合约建立的时候就肯定好了的,它取决于合约所声明状态变量。可是内容能够被(交易)调用改变。
Solidity 称这个为状态改变,这也是合约级变量称为状态变量的缘由。也能够更好的理解为何状态变量都是storage存储。
memory 只能用于函数内部,memory 声明用来告知EVM在运行时建立一块(固定大小)内存区域给变量使用。
storage 在区块链中是用key/value的形式存储,而memory则表现为字节数组
EVM是一个基于栈的语言,栈实际是在内存(memory)的一个数据结构,每一个栈元素占为256位,栈最大长度为1024。 值类型的局部变量是存储在栈上。
咱们也推出了目前市面上最全的视频教程:深刻详解以太坊智能合约语言Solidity 目前咱们也在招募课程体验师,能够点击连接了解。
☛ 深刻浅出区块链 - 系统学习区块链,打造最好的区块链技术博客。
☛ 个人知识星球为各位解答区块链技术问题,欢迎加入讨论。
☛ 关注公众号“深刻浅出区块链技术”第一时间获取区块链技术信息。