Solidity函数参数:为何string需指定memory而uint无需?哪些类型需指定?
函数参数的memory修饰符疑问解答
先看你给出的示例代码:
contract SimpleContract{ string favWord; uint favNum; // 此处有两个参数_favNum和_favWord,其中_favWord需要指定memory function simpleFunction(uint _favNum, string memory _favWord) public { favNum = _favNum; favWord = _favWord; } }
为什么string参数要加memory,uint不用?
根源在于Solidity对数据类型的划分:值类型和引用类型的存储机制完全不同。
1. uint属于值类型,无需指定存储位置
uint(包括int、bool、address、固定大小数组如uint[5]等)是值类型。这类变量直接存储数据本身,当作为函数参数传递时,会把整个值复制到函数的栈空间里——栈是Solidity默认给值类型分配的临时存储区域,编译器会自动处理,所以不需要显式加任何存储修饰符。
2. string属于引用类型,必须指定存储位置
string(包括bytes、动态数组、结构体等)是引用类型。这类变量不存数据本身,只存指向数据的引用地址。Solidity有三种存储位置:
memory:临时内存,函数执行完就释放,适合临时处理参数数据storage:合约永久存储区,数据会持久保存calldata:外部函数的输入数据区,只读且更省gas
作为函数参数时,必须明确告诉编译器该引用类型的存储位置,否则编译器无法确定数据的读取/存储位置,直接报错。所以string参数必须加memory(外部函数也可以用calldata)。
哪些类型作为函数参数必须指定存储位置?
所有引用类型都需要显式指定存储位置,包括:
- 动态字节类型:
bytes - 字符串类型:
string - 动态数组:比如
uint[]、address[]等 - 自定义结构体(struct)
- 映射(mapping,不过映射几乎只作为合约storage变量使用,很少直接当函数参数)
注意:固定大小数组(如uint[10])属于值类型,作为函数参数时不需要指定存储位置。
内容的提问来源于stack exchange,提问作者Zura Gabichvadze
相关产品推荐
相关产品推荐

