Solidity中memory与storage区别及函数参数存储位置疑问
pragma solidity >=0.5.0 <0.6.0; contract ZombieFactory { uint dnaDigits = 16; uint dnaModulus = 10 ** dnaDigits; struct Zombie { string name; uint dna; } Zombie[] public zombies; function createZombie (string memory _name, uint _dna) public { // start here } }
问题结论
你示例代码中作为函数参数传入的string类型_name,会被分配到memory临时存储空间,不会存储到合约的持久化storage中。
规则说明
你看到的相关说明内容为:
结构体的局部变量默认存储在storage中,但函数参数始终存储在memory中
该表述符合Solidity的设计逻辑,结合你使用的0.5.x版本Solidity的规则,可以拆解为几点:
- Solidity 0.5.0及之后的版本强制要求:所有引用类型(string、动态数组、结构体、bytes等)必须显式声明数据位置,不存在隐式默认分配。你的代码中已经为
_name参数显式添加了memory关键字,本身就是明确指定该参数存储在调用期间临时分配的内存空间中,函数执行结束后该空间就会被回收,不会上链持久化。 - 所谓“结构体局部变量默认存储在storage”,特指在函数内部声明结构体类型的局部变量、且未显式指定数据位置的场景,这类变量默认是storage指针,会直接指向合约的持久化存储槽,修改操作会直接变更合约状态。
- 函数参数永远不会默认分配到storage空间:值类型参数(比如你代码中
uint类型的_dna)通过值传递存在调用栈中;引用类型参数必须手动标记为memory或calldata(只读临时存储,gas成本更低),仅在函数调用生命周期内有效。
不同存储位置的核心差异
storage:合约的持久化链上存储,写入和修改的gas成本极高,只有合约状态变量(比如你代码中的dnaDigits、zombies数组)默认分配在该空间,数据修改后会永久上链留存。memory:函数调用期间临时分配的内存,读写gas成本低,调用结束后自动释放,不会持久化到链上,函数临时变量、显式标记memory的参数都分配在该空间。calldata:只读的临时存储空间,一般用于外部函数的入参读取,gas成本比memory更低,数据同样不会上链持久化。
补充说明:如果你后续要在createZombie函数中把传入的_name存入zombies这个storage数组,Solidity会自动完成值拷贝,不会直接把参数的存储位置改成storage。
内容的提问来源于stack exchange,提问作者Tushar Singh
相关产品推荐
相关产品推荐

