区块链:Solidity值传递&值类型与引用类型

Solidity值传递

pragma solidity ^0.4.4;

contract Person{
    uint _age;

    function Person(uint age) {
        _age = age;
    }

    function f(){
        modify(_age);
    }

    function modify(uint age){
        age = 100;
    }

    function age() constant returns (uint){
        return _age;
    }
}

区块链:Solidity值传递&值类型与引用类型_第1张图片

Solidity引用类型(storage/memory)

pragma solidity ^0.4.4;

contract Person{
    string _name;

    function Person(string name) {
        _name = name;
    }

    function f(){
        modify(_name);
    }

    //memory storage
    function modify(string storage name) internal{

        bytes(name)[0] = "S";
    }

    function name() constant returns (string){
        return _name;
    }
}

区块链:Solidity值传递&值类型与引用类型_第2张图片

Solidity值类型与引用类型

也许对于很多有开发经验的童鞋来说,大家会以为Solidity语法非常简单,其实不然,Solidity还是存在很多和其他语言不一样的坑,下面是Solidity相关语法细节以及注意事项

先来看看有哪些类型属于值类型,哪些属于引用类型。

值类型(Value Type)

值类型包含:

  • 布尔(Booleans)
  • 整型(Integer)
  • 地址(Address)
  • 定长字节数组(fixed byte arrays)
  • 有理数和整型(Rational and Integer Literals,String literals)
  • 枚举类型(Enums)
  • 函数(Function Types)

有其他语言开发经验的童鞋都知道,值类型传值时,会临时拷贝一份内容出来,而不是拷贝指针,当你修改新的变量时,不会影响原来的变量的值。

例如:

int a = 100;  // a == 100
int b = a;   // b == 100,a == 100
b = 300;    // b == 300,a == 100

由上面的数据看,执行 b = a时,会将a的值临时拷贝一份传给b,所以当你修改b时,其实与a没任何关系

引用类型(Reference Types)

引用类型包含:

  • 不定长字节数组(bytes)
  • 字符串(string)
  • 数组(Array)
  • 结构体(Struts)

引用类型,赋值时,我们可以值传递,也可以引用即地址传递,如果是值传递,和上面的案例一样,修改新变量时,不会影响原来的变量值,如果是引用传递,那么当你修改新变量时,原来变量的值会跟着变化,这是因为新就变量同时指向同一个地址的原因。

引用类型中如何类比值传递

值传递伪代码(以iOS中可变字符串NSMutableString为例子):

//创建一个可变的字符串name
NSMutableString *name = [@"wt" mutableCopy];  // name == "wt"

NSMutableString *name1 = [name copy]; //name1 == "wt", name == "wt"

name1 = "十二指环"; //name1 == "十二指环",name == "wt"

引用类型中如何类比引用传递

//创建一个可变的字符串name
NSMutableString *name = [@"wt" mutableCopy];  // name == "wt"

NSMutableString *name1 = name; //name1 == "wt", name == "wt"

name1 = "十二指环"; //name1 == "十二指环",name == "十二指环"

引用类型memory/storage

引用类型的变量有两种类型,分别是memorystorage
memory(值传递)默认

当引用类型作为函数参数时,它的类型默认为memory,函数参数为memory类型的变量给一个变量赋值时,这个变量的类型必须和函数参数类型一致,所以我们可以写成string memory name1 = name;,或者var name1 = name;,var声明一个变量时,这个变量的类型最终由赋给它值的类型决定。

任何函数参数当它的类型为引用类型时,这个函数参数都默认为memory类型,memory类型的变量会临时拷贝一份值存储到内存中,当我们将这个参数值赋给一个新的变量,并尝试去修改这个新的变量的值时,最原始的变量的值并不会发生变化。

storage(指针传递)

pragma solidity ^0.4.4;

contract Person {

    string public  _name;

    function Person() {
        _name = "wt";
    }

    function f() {

        modifyName(_name);
    }

    function modifyName(string name)  {

        var name1 = name;
        bytes(name1)[0] = 'W';
    }
}

当函数参数为memory类型时,相当于值传递,而storage类型的函数参数将是指针传递

如果想要在modifyName函数中通过传递过来的指针修改_name的值,那么必须将函数参数的类型显示设置为storage类型,storage类型拷贝的不是值,而是_name指针,当调用modifyName(_name)函数时,相当于同时有_name,name,name1三个指针同时指向同一个对象,我们可以通过三个指针中的任何一个指针修改他们共同指向的内容的值。

备注:

function modifyName(string storage name)  {

    var name1 = name;
    bytes(name1)[0] = 'L';
}

等价于:

function modifyName(string storage name)  {

    string storage name1 = name;
    bytes(name1)[0] = 'L';
}

上面的代码会在Remix中编译报错,原因是函数默认为public类型,但是当我们的函数参数如果为storage类型时,函数的类型必须为internal或者private

正确代码

pragma solidity ^0.4.4;

contract Person {

    string public  _name;

    function Person() {
        _name = "liyuechun";
    }

    function f() {

        modifyName(_name);
    }

    function modifyName(string storage name) internal {

        var name1 = name;
        bytes(name1)[0] = 'L';
    }
}

小结

Solidity编程语言中有哪些是值类型,哪些是引用类型,以及值类型和引用类型的区别我们进行简单的区分。【PS:Solidity值类型中,赋值时我们始终记住传的是值,改变新变量,不会影响原值,而引用类型就有两种可能】

在引用类型中的memorystorage的正确使用,才能不影响值的变化。

你可能感兴趣的:(区块链)