import{_ as i,c as a,a as n,o as l}from"./app-BwvsBlHw.js";const h={};function e(k,s){return l(),a("div",null,[...s[0]||(s[0]=[n(`
storage:合约的持久化状态数据,保存在链上状态。对 storage 的写入最昂贵,读取也比内存贵;修改会永久生效。memory:函数调用期间的临时数据,函数返回后即释放。对 memory 的更改不会持久化。calldata:外部函数参数的只读数据位置,零拷贝、不可修改,用于节省 gas。storage 写入昂贵、读取较贵;适合保存需要长期存在的状态。memory 在函数结束时释放,读取/写入相对便宜;适合临时计算与返回值。struct、mapping、string、bytes)在函数参数或局部变量处通常必须显式标注数据位置。storage(例如 User[] public users;)。external)的复杂类型参数默认是 calldata;内部/公共函数需要显式标注 memory 或 storage。storage 读取到 memory 会“复制”数据;修改 memory 副本不影响原始 storage。storage 局部变量可以得到对状态数据的“引用”,对其赋值会持久化。pragma solidity ^0.8.20;
contract Users {
struct User { string name; uint age; }
User[] public users;
function add(string memory name, uint age) external {
users.push(User(name, age)); // 写入 storage
}
function updateName(uint i, string memory newName) external {
User storage u = users[i]; // storage 引用(指向链上状态)
u.name = newName; // 修改持久化生效
}
function tryUpdate(uint i) external {
User memory u = users[i]; // 从 storage 复制到 memory
u.age = 99; // 仅修改副本,不会影响链上状态
}
}storage 引用参数,从而直接修改状态;外部函数参数不能是 storage。pragma solidity ^0.8.20;
contract Users2 {
struct User { string name; uint age; }
User[] public users;
function _inc(User storage u) internal { u.age += 1; }
function birthday(uint i) external {
_inc(users[i]); // 传递 storage 引用,持久化修改
}
}memory 中构造动态数组:new uint[](n);适合作为返回值或临时计算。mapping 只能存在于 storage,不能在 memory 中创建或拷贝。pragma solidity ^0.8.20;
contract Arrays {
function make(uint n) external pure returns (uint[] memory a) {
a = new uint[](n);
for (uint i = 0; i < n; i++) a[i] = i;
}
}storage 变量整体赋值会进行深拷贝或引用变更(依据类型),要明确拷贝成本与语义。memory 副本不会持久化;要修改链上状态请使用 storage 引用。string/bytes/数组 在 memory↔storage 间复制成本高,尽量减少不必要的复制。calldata 的地方尽量使用(只读参数),节省 gas。