solidity编程中遇到的各种问题--数据结构篇
Posted 一袋芋头
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了solidity编程中遇到的各种问题--数据结构篇相关的知识,希望对你有一定的参考价值。
solidity的数据结构
1.Mapping的删除
情景:在完成合约的一些交易后要将本次使用过的一些mapping数据删除(或重置),以供下次或其他人使用合约的状态变量
注意:
mapping的delete:只是删除对应某个key的value,而不能直接删除整个mapping,所以要想删除该mapping的每一个key时,往往要把每一个key放进一个动态数组,然后遍历该数组进行删除。
问题:如果要删除一个mapping里的另一个mapping,是直接删除外层mapping,还是要把里层mapping的每个Key都删除?
测试:
// SPDX-License-Identifier: SimPL-2.0
pragma solidity ^0.4.18;
struct result
int[] results;
mapping(int => uint) resultcount;
mapping(address => result) CSToResult;
//设置值
function setresults(int _result, uint _count)public
CSToResult[msg.sender].results.push(_result);
CSToResult[msg.sender].resultcount[_result] = _count;
//获取results数组和对应某一个result的count
function getresults(int _result) public view returns(int[],uint)
return (CSToResult[msg.sender].results,CSToResult[msg.sender].resultcount[_result]);
/*
以下将采取三种方式对CSToResult这个mapping进行删除
1.直接删除CSToResult[msg.sender];
2.删除CSToResult[msg.sender]中的每一个result的count及results数组;
3.在2的基础上再删除删除CSToResult[msg.sender];
*/
function deleteData1()public
delete CSToResult[msg.sender];
function deleteData2()public
for(uint i =0; i <CSToResult[msg.sender].results.length;i++)
delete CSToResult[msg.sender].resultcount[CSToResult[msg.sender].results[i]];
delete CSToResult[msg.sender].results;
function deleteData3()public
for(uint i =0; i <CSToResult[msg.sender].results.length;i++)
delete CSToResult[msg.sender].resultcount[CSToResult[msg.sender].results[i]];
delete CSToResult[msg.sender].results;
delete CSToResult[msg.sender];
注意:
这里不能把CSToResult设置成public的
我觉得是因为结构体里边含了个动态数组的缘故(之前用过结构体里含一个mapping,也可以设置成public类型,所以应该不是内层mapping的问题)
下面对每一种方法进行测试;
我们分别把1,1;
2,2;
3,3;
3,5 push进去,然后分别用三个函数进行删除,观察删除效果及gas消耗情况
注意:gas cost可以分为Execution cost和transaction cost
Execution cost包括存储全局变量以及方法调用相关的运行环境的开销。同一个函数,每次调用时的execution cost有可能是不同的。(比如全局变量发生了变化导致)
而Transaction cost和编译后的合约代码长度相关,也和execution cost相关。同一个合约,每次执行时transaction cost - execution cost的值应该是不变的。
删除前先查看一下
1.直接删除CSToResult[msg.sender]:调用deleteData1()
gas消耗:
再查看一下
发现,仅仅将大Mapping对应struct里的其他数据结构变为了初值,里层的mapping其实是不受影响的。
2.调用deleteData2()
gas消耗:
再查看一下
这次基本上成功了,但是不知道外层mapping有没有成功删除。
3.调用deleteData3()
gas消耗:
再查看一下
和2的效果是一样的,但是gas明显多了,所以删除外层mapping应该是有用的。
…写到这里我又想到了第四种方法,就是不删除结构体里的动态数组,反正结果是一样的。。稍微测试了一下
function deleteData4()public
for(uint i =0; i <CSToResult[msg.sender].results.length;i++)
delete CSToResult[msg.sender].resultcount[CSToResult[msg.sender].results[i]];
// delete CSToResult[msg.sender].results;
delete CSToResult[msg.sender];
效果一样,gas比方法3稍微少一点,也只比2多了百十wei,…还不错
总结:要想保险一点,要把内层mapping删除,再把外层mapping删除,这样应该是技能达到效果又能省亿点点gas的吧
以上是关于solidity编程中遇到的各种问题--数据结构篇的主要内容,如果未能解决你的问题,请参考以下文章