通学智能合约系列(十九)--memory与storage
Posted 通学技术
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了通学智能合约系列(十九)--memory与storage相关的知识,希望对你有一定的参考价值。
Solidity-内存、引用与持久化存储
1、 内存与区块链——storage与memory原理
在前面的学习当中,我们知道了,合约中的一个被public
修饰的成员变量,会默认生成一个供外部调用的函数,而这个函数是存储在区块链自身的数据结果里的。对于函数内部的局部变量,仅存在与内存当中。
我们看如下例子:
pragma solidity ^0.4.16;
contract MemoryTest
function add(uint num) view returns(uint)
num += 1;
return num;
function test() view returns(uint,uint)
uint i = 2;
uint j = add(i);
return(i,j);
编译执行以上代码后,可以得到以下结果:
当我们改变输入的num
的值,尽管add
函数的返回值是变化的,但是我们test()
函数的返回值,始终是2
和3
.原因是什么呢?就是因为我们的i
和j
作为局部变量,在设置num
值给add()
函数的时候,仅仅是拷贝了一份副本数据给变量i
,而实际参数i
是确定被赋值为2的。所以j
的值也是恒定为3
的。这个地方大家可以类比java
中的形参和实参。
具体的内存模型如下图:
关于我们的变量num
,i
,j
其实都是存储在memory
中的,当合约函数被执行完成之后,这些内存数据也就消失了。而对于我们的成员变量,也可能理解成我们的合约函数,是存储在storage
当中的,这些数据会被永久保存。
上图,我们画的公有成员变量k
,我们来尝试修改它吧。
uint public k = 20;
function changeIt()
add(k);
编译执行之后,我们发现k
值是不会发生变化的。这个相当于将区块链上的数据k
重新拷贝了一份到add()函数
的
形参i
中去做运算,实际上k
的值是不会变化的。
我们下面再来看一个例子:
pragma solidity ^0.4.16;
contract MemoryTest
uint public num1 = 5;
uint public num2 = num1;
function test() view returns(uint)
uint i = num1;
uint j = i;
j++;
return i;
function test2() view returns(uint)
uint i = num1;
uint j = i;
i++;
return i;
经过编译执行后,我们发现,以上各个变量之间都是彼此独立,互不影响的。各自有自己的内存空间,修改是不会影响其他变量的。
以上我们介绍的都是我们的memory
内存。
在写这篇文章的时候,我脑海中对自己提出了一个疑问,那就是智能合约到底存在哪里?
经过一番搜索,找到以下以下答案,供大家一起探讨,如果你有好的想法,可以留言发表呀~
2、 storage引用详解
在这一小节中,我们将重点介绍storage
内存。
如果小伙伴们有接触过java
的内存分配模型,应该都知道java
的基本类型是存储在栈中的,而对象的内容或者数组的内容是存储在堆中的。如下图。
这里我们为什么要提到堆栈呢?主要还是因为这solidity
中的memory
和storage
就类同于我们java
的栈
和堆
啊,有没有?
下面我们来看一段代码
pragma solidity ^0.4.16;
contract StorageTest
// 这个状态变量存储在区块链的网络之上
uint[] arrx;
// 当我们传递这个可变长度数组的时候,会在内存中为它分配空间
function test(uint[] arry) view returns(uint[])
// 将内存的arry拷贝给区块链上的arrx变量
arrx = arry;
// 当我们在函数体内部定义了一个可变长度的数组时,实际上,他默认的类型是storage类型。
uint[] z = arrx;
return z;
针对storage
类型的操作
pragma solidity ^0.4.16;
contract StorageTest
uint[] arrx;
function test(uint[] arry) view returns(uint)
arrx = arry;
// 当我们在函数体内部定义了一个可变长度的数组时,实际上,他默认的类型是storage类型,
他指向了区块链上的arrx,所以当我修改z的元素的时候,我们实际上再操作的是区块链上的arrx
uint[] z = arrx;
// 通过指针实际身上修改了区块链上的arrx的值
z[0] = 100;
//通过指针实际上修改了区块链上arrx的长度,说明z和zrrx其实是一样的,操作z的时候,会改变arrx的值。
z.length = 100;
return z[0];
// 返回arrx的第一个元素
function test2() returns(uint)
return arrx[0];
// 返回arrx的长度
function test3() returns(uint)
return arrx.length;
关于solidity
的两种内存特性就介绍到这里。
通学技术 面向区块链编程 学通技术 构建可信任社会
以上是关于通学智能合约系列(十九)--memory与storage的主要内容,如果未能解决你的问题,请参考以下文章