pragma solidity >=0.7.0 <0.9.0;
contract Storage {
string[] messages;
uint256 bidPrice;
constructor() payable {
bidPrice = msg.value * 10001 / 10000;
}
function store(string calldata message) public payable {
if (msg.value < bidPrice) revert( "Payment not enough" );
messages.push(message);
bidPrice = bidPrice * 10001 / 10000;
}
function retrieve(uint index) public view returns (string calldata){
return messages[index];
}获取错误:
TypeError: Return argument type string storage ref is not implicitly convertible to expected type (type of first return variable) string calldata.
--> contracts/1_Storage.sol:20:16:
|
20 | return messages[index];
| ^^^^^^^^^^^^^^^它只是作为返回类型与memory string一起工作,但是:
calldata返回类型有用吗?在什么情况下?发布于 2022-01-02 05:19:02
calldata只适用于输入参数。它不适用于返回的值。
发布于 2022-01-04 02:42:19
为什么我会有这个错误?
您正在尝试返回一个在存储中而不是在调用数据中的值。要使其工作,编译器必须将您的字符串复制到calldata区域,这是不可能的,因为回调数据是只读的。有记忆就没问题了。
但是,如果调用数据中已经包含了某些内容,则可以返回它。例如,下面是一个函数,它将返回回调字符串的一个片段:
function substring(string calldata input, uint begin, uint end)
public
view
returns (string calldata)
{
return input[begin:end];
}有一个
calldata返回类型有用吗?在什么情况下?
返回已在调用数据中的内容比返回memory值便宜,因为编译器可以跳过ABI编码。如果可以的话你肯定想这么做。
尽管如此,实际应用这种优化的机会并不是很普遍。这是非常符合情况的。下面是一些我可以从头顶上想到的例子:
memory替换calldata,因此您可以拥有一个泛型函数,该函数在接口中返回memory值,然后在特定的实现中使用calldata,而该实现恰好对其输入不做任何操作,并将其返回不变。calldata返回,函数将不得不将整个切片复制到内存中。相反,您可以返回片的偏移量和长度,但这基本上是calldata片内部的内容。编译器可以为你做这件事。calldata值进行完全操作,包括返回它们并将它们存储在局部变量中,则可以保留当您坚持类型系统时通常得到的一些优势。其中一个事实是,在实际使用calldata值之前不会对它们进行解码。您不会在abi.decode()中得到这一点,因为它会急切地解码到内存中。下面是一个接受在原始bytes数组中编码的结构并将其提取到calldata变量的示例: contract { struct { uint;}函数convertToS(字节回调数据输入)内部纯返回(S回调数据结果){程序集{成绩:= input.offset }函数运行(字节调用数据输入)外部纯返回(run数据结果){ calldata =convertToS(输入32:);返回s;}也许还有更多,但我想你明白了。这不是一个经常使用的特性,但有时它很好。
https://ethereum.stackexchange.com/questions/117770
复制相似问题