solidity0.5.x笔记(2)-引用类型

本文详细介绍了Solidity中引用类型的三种数据位置:memory、storage和calldata,包括它们的特性、赋值规则和 gas 消耗。接着讨论了数组的使用,包括定长和动态数组的创建、成员操作以及多维数组和bytes与string的区别。此外,还深入探讨了映射的声明、支持的类型和getter方法。最后,讲解了结构体的定义、初始化和使用限制,以及结构体在继承和跨合约场景下的处理方式。
摘要由CSDN通过智能技术生成

引用类型的数据位置

不同于之前值类型,引用类型占的空间更大,超过256字节,因为拷贝它们占用更多的空间。由此我们需要考虑将它们存储在什么位置内存(memory,数据不是永久存在的)或存储(storage,数据永久的保存在数据块上)

引用类型数据位置分类

  • memory
  • storage
  • calldata
memory

存储位置同我们普通程序的内存类似。即分配,即使用,越过作用域即不可被访问,等待被回收。

storage

数据将永远存在于区块链上。

calldata

一般只有外部函数的参数(不包括返回参数)被强制指定为calldata。这种数据位置是只读的,不会持久化到区块链,效果跟 memory 差不多。

注意:
1. 函数参数、返回值、函数内局部变量,引用类需要强制指定存储位置
2. 返回值只能指定memory位置
3. 引用类型的状态变量只能存储在storage, 且不能指定

不同数据位置变量间相互赋值

storage与storage相互赋值

当我们把一个storage类型的变量赋值给另一个storage时,只是修改了它的指针(引用传递)。

pragma solidity ^0.5.0;


contract StorageConvertToStorage{
   
  struct S{
   string a;uint b;}

  //默认是storage的
  S public s;

  function convertStorage(S storage _s) internal{
   
    _s.a = "hello";
    _s.b = 100;
  }

  function call() public returns (string memory){
   
    convertStorage(s);
    return s.a;//Test
  }
}

在上面的代码中,我们将传入的storage变量,并修改_s.a = “hello”,最后我们发现合约的状态变量s也被修改了。

memory给storage赋值

因为局部变量和状态变量的类型都可能是storage。所以我们要分开来说这两种情况。

1.memory赋值给状态变量

将一个memory类型的变量赋值给一个状态变量时,实际是将内存变量拷贝到存储中。

pragma solidity ^0.5.0;


contract MemoryConvertToStateVariable{
   
  struct S{
   string a;uint b;}

  //默认是storage的
  S public s;
 
 constructor()public {
   

 }


  function memoryToState()  internal{
   

        S memory m_s;
        m_s.a = "hello";
        m_s.b = 100;
        
        s = m_s;
       
        m_s.a = "world";
        m_s.b = 99;
  }
  function call()  public {
   
    memoryToState();
  }
}

通过上例,我们发现,在convertStorage()中,我们把m_s赋值给s后,再修改m_s值,并不能使s产生任何变化。赋值时,完成了值拷贝,后续他们不再有任何的关系。

2.memory赋值给局部变量

由于在区块链中,storage必须是静态分配存储空间的。局部变量虽然是一个storage的,但它仅仅是一个storage类型的指针。如果进行这样的赋值,实际会产生一个错误。

pragma solidity ^0.5.0;


contract MemoryToLocalVar{
   
  struct S{
   string a;uint b;}

    S s;
  constructor()public{
   
      s.a = "hello";
      s.b = 10;
  }
  function memoryToLocal(S memory _s) internal{
   
    
    //Type struct MemoryToLocalVar.S memory is not implicitly convertible to expected type struct MemoryToLocalVar.S storage pointer.
    S storage tmp = _s;  
  }
  
    function call() view public {
   
    memoryToLocal(s);
  }
}

通过上面的代码,我们可以看到这样的赋值的确不被允许。

storage转为memory

将storage转为memory,实际是将数据从storage拷贝到memory中。

pragma solidity ^0.5.0;


contract StorageToMemory{
   
  struct S{
   string a;uint b;}

  S public s = S("hello", 100);

  function storageToMemory() view  internal{
   
    S memory tmp = s;
    
    //memory的修改不影响storage
    tmp.a = "world";
  }

  function call() view public{
   
    storageToMemory();

  }
}

在上面的例子中,我们看到,拷贝后对tmp变量的修改,完全不会影响到原来的storage变量。

memory转为memory

memory之间是引用传递,并不会拷贝数据。我们来看看下面的代码。


                
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值