在Solidity中,storage
和memory
是用于声明和处理数据的两个关键字,它们具有不同的用途和作用域。
一、storage
storage
关键字用于声明永久存储在区块链上的数据,也就是合约的状态变量。使用storage
关键字声明的变量将持久保存在区块链上,直到合约被销毁。对于storage
变量,数据存储在合约的存储空间中,并且状态的更改将永久记录在区块链上。默认情况下,合约的状态变量是storage
类型。
在函数参数中使用storage
关键字是无效的,因为storage
关键字只用于声明合约的状态变量,而不适用于函数的形参,否则会报错。但在以下情况中必须使用:
//角色库(管理所有角色地址)
// 1. 实现增加角色地址
// 2. 移除角色地址
// 3. 判断角色地址是否被授权
library Roles {
struct Role {
mapping (address=>bool) bearer;
}
function add(Role storage role,address account) internal {
require(!has(role,account),"account already has role");
role.bearer[account] = true;
}
function remove(Role storage role,address account) internal {
require(has(role,account),"account does not have role");
role.bearer[account] = false;
}
function has(Role storage role,address account) internal view returns(bool){
require(account != address(0),"account is not zero address");
return role.bearer[account];
}
}
此处storage
关键字用于指定在函数参数中使用的是对状态变量的引用,而不是复制状态变量的值。这样可以直接修改传入的状态变量,而不是创建一个新的副本。
在上述代码中,函数add
、remove
和has
中的Role storage
参数表示将Role
结构体作为引用传递,以便直接修改传入的Role
对象。
二、memory
memory
关键字用于声明临时数据,主要用于函数内部的局部变量和函数参数。memory
中的数据只在函数执行期间存在,函数执行完毕后将被清除,不会永久存储在区块链上。在函数之间传递大量数据时,使用memory
关键字可以避免消耗过多的燃料(Gas)。
三、用法
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;
contract StorageTest {
uint256 public data; // 默认为storage类型
///storage:storage关键字用于声明永久存储在区块链上的数据,也就是合约的状态变量。
///使用storage关键字声明的变量将持久保存在区块链上,直到合约被销毁。
///对于storage变量,数据存储在合约的存储空间中,并且状态的更改将永久记录在区块链上。默认情况下,合约的状态变量是storage类型。
function setData(uint256 _data) external {
data = _data;
}
///memory:memory关键字用于声明临时数据,主要用于函数内部的局部变量和函数参数。
///memory中的数据只在函数执行期间存在,函数执行完毕后将被清除,不会永久存储在区块链上。在函数之间传递大量数据时,使用memory关键字可以避免消耗过多的燃料(Gas)。
function concatenate(string memory _a, string memory _b) public pure returns (string memory) {
bytes memory a = bytes(_a);
bytes memory b = bytes(_b);
bytes memory result = new bytes(a.length + b.length);
uint256 k = 0;
for (uint256 i = 0; i < a.length; i++) {
result[k++] = a[i];
}
for (uint256 i = 0; i < b.length; i++) {
result[k++] = b[i];
}
return string(result);
}
}
在上述示例中,data
变量是一个状态变量,其类型为uint256
,它存储在合约的存储空间中。
concatenate
函数接受两个字符串参数,声明为memory
类型,表示这些数据是临时的。在函数内部,我们使用bytes
类型来操作字符串,将两个字符串连接起来并返回结果。
四、区别
storage用于声明合约的状态变量,数据存储在合约的存储空间中,持久保存在区块链上。
memory用于声明函数的局部变量和参数,数据仅在函数执行期间存在,不保存在区块链上。
使用storage和memory关键字可以明确指定数据的作用域和存储方式,提高代码的效率和安全性。