变量使用
解决问题:
- 数据类型:
- 什么是值类型
- 什么是引用类型
- 使用方式:
- 值传递
- 引用传递
数据类型:
- 值类型:变量的存储空间存的是变量的数据 —(全部皆为值传递)
- 引用类型:变量的存储空间存的是变量数据所在的存储空间的地址
数据传递:
- 值传递和引用传递。值类型的变量,赋值是简单的值传递,即两个变量占有独立的存储区域。引用类型赋值传递的是变量的引用,即两个变量指向同一存储区域
- 实例:A向B索求某个URL,如果B给A这个URL,那么A与B都将共享这个网页,如果A与B某一方修改了这个网页,那么这种变化两者都是可见的; –引用传递
但是如果B是将这个网页打印出来,然后给A,那么B无论之后对这个网页做出什么改变,那么A将不会看到。–值传递
细节使用
- 如果一个变量是值类型,给它赋值时永远是值传递,函数参数传递时永远是值传递;
- 如果一个变量是引用类型,给它赋值时可以是值,也可以是引用,这决定于该变量是Storage类型还是Memory类型。
solidity中变量类型
- 值类型
- 布尔(Booleans)
- 整型(Integer)
- 地址(Address)
- 定长字节数组(fixed byte arrays)
- 有理数和整型(Rational and Integer Literals,String literals)
- 枚举类型(Enums)
2.引用类型
- 不定长字节数组(bytes)
- 字符串(string)
-数组(Array)
-结构体(Struts)
solidity 代码实例
当函数参数为memory类型时,相当于值传递,而storage类型的函数参数将是指针传递。
- 值传递与引用传递 代码来自于
contract SandwichFactory {
struct Sandwich {
string name;
string status;
}
Sandwich[] sandwiches;
function eatSandwich(uint _index) public {
// Sandwich mySandwich = sandwiches[_index];
/*
看上去很直接,不过 Solidity 将会给出警告,告诉你应该明确在这里定义 `storage` 或者 `memory`。
所以你应该明确定义 `storage`:
*/
Sandwich storage mySandwich = sandwiches[_index];
// 这样 `mySandwich` 是指向 `sandwiches[_index]`的指针在存储里,另外...
mySandwich.status = "Eaten!";
// 这将永久把 `sandwiches[_index]` 变为区块链上的存储,如果你只想要一个副本,可以使用`memory`:
Sandwich memory anotherSandwich = sandwiches[_index + 1];
// 这样 `anotherSandwich` 就仅仅是一个内存里的副本了
// 另外
anotherSandwich.status = "Eaten!";
// 将仅仅修改临时变量,对 `sandwiches[_index + 1]` 没有任何影响
// 不过你可以这样做:
sandwiches[_index + 1] = anotherSandwich;
// 如果你想把副本的改动保存回区块链存储
}
}
- 关于memory与solidity不同类型赋值情况
- 存储变量到存储变量 – 创建数据副本(数据副本仅仅是对赋值数据的拷贝)
- 存储变量到内存变量 – 创建数据副本
- 内存变量到存储变量 – 创建数据副本
- 内存变量到内存变量 – 对于引用类型的局部变量,从一个内存变量到另一个数据变量不会产生副本(引用传递),
对于值类型的局部变量,仍然会创建一个数据副本(值传递)
contract LocationsFromStoS {
// M -- memory S --- storage
//修改第二变量的值,仅仅是为了整明第一变量获取到的仅仅是第二个变量的数据拷贝
uint public stateVar1 = 10;
uint stateVar2 = 20;
function doSomething() public returns (uint, uint) {
stateVar1 = stateVar2;
stateVar2 = 30;
return (stateVar1, stateVar2); //returns 20,30
}
}
contract LocationsFromMtoS {
uint public stateVar = 10; //storage
function doSomething(uint _x) public returns(uint, uint) {
stateVar = _x;
_x = 21;
return (stateVar, _x); //returns 20,40
}
}
contract LocationsFromStoM {
uint stateVar = 10; //storage
string public name = "renln";
function doSomething() public returns(uint, uint) {
uint localVar = 20; //memory
localVar = stateVar;
stateVar = 40;
return (localVar, stateVar); //returns 10,40
}
function doSomething1(string memory _localname) public returns(string memory) {
// bytes memory btsName = bytes(name);
bytes memory btsLocalname = bytes(_localname);
name = string(btsLocalname);
btsLocalname = "Renln";
return (string(btsLocalname));
}
}
contract LocationsFromMtoM {
//引用类型
function doSomething()
public pure returns(uint[] memory, uint[] memory) {
uint[] memory localMemoryArray1 = new uint[](3);
localMemoryArray1[0] = 4;
localMemoryArray1[1] = 5;
localMemoryArray1[2] = 6;
uint[] memory localMemoryArray2 = localMemoryArray1;
localMemoryArray1[0] = 10;
return (localMemoryArray1, localMemoryArray2);
//returns 10,5,6 | 10,5,6
}
//值类型 修改_localVar2只是为了整明—_localVar1是获取到_localVar1的数据拷贝
function doSomething1(uint _localVar1, uint _localVar2) public pure returns(uint, uint) {
_localVar1 = _localVar2; // _localVar1:11,_localVar2:22
_localVar2 = 40;
return (_localVar1, _localVar2); //returns 20
}
}