本文主要是介绍通学智能合约系列(十九)--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的元素的时候,我们实际上再操作的是区块链上的arrxuint[] 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的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!