函数的返回参数数据位置必须为“memory”,但未给出。

52

我在remix中尝试了上面的solidity样例,使用的是solidity版本大于0.5.0。 但现在我遇到了这个错误。 有什么方法可以解决这个错误吗?

contract MyContract {
    string value;

    function get() public view returns (string) {
        return value;
    }

    function set(string _value) public {
        value = _value;
    }

    constructor() public {
        value = "myValue";
    }
}
5个回答

86

你应该为字符串参数添加memory关键字,这个关键字在solidity版本0.5.0中引入。

根据文档:

结构体、数组或映射类型的所有变量都需要显式地指定数据位置。函数参数和返回值也是如此。例如,将uint [] x = m_x更改为uint [] storage x = m_x ,将函数f(uint [] [] x)更改为函数f(uint [] [] memory x),其中memory是数据位置,可以相应地替换为storage或calldata。请注意,外部函数要求具有calldata数据位置的参数。

已更正的代码

contract MyContract {
    string value;

    function get() public view returns (string memory) {
        return value;
    }

    function set(string memory _value) public {
        value = _value;
    }

    constructor() public {
        value = "myValue";
    }
}

请参考官方文档,了解版本0.5.0中的重大变更。


18
引用类型的值可以通过多个不同的名称进行修改。与值类型相反,每当使用值类型的变量时,都会获得独立的副本。因此,引用类型必须比值类型更加小心处理。目前,引用类型包括结构体、数组和映射。如果使用引用类型,则必须始终明确提供存储类型的数据区域:内存(其生命周期仅限于外部函数调用)、存储器(状态变量存储的位置,其生命周期仅限于合约的生命周期)或 calldata(包含函数参数的特殊数据位置)。
警告
在版本0.5.0之前,数据位置可以省略,并且默认为不同的位置,具体取决于变量、函数类型等的种类,但现在所有复杂类型都必须给出显式的数据位置。

https://docs.soliditylang.org/en/latest/types.html#reference-types

所以你必须在String后面加上memorycalldata,如下所示:
contract MyContract {
    string value;

    function get() public view returns (string memory) {
        return value;
    }

    function set(string memory _value) public {
        value = _value;
    }

    constructor() {
        value = "myValue";
    }
}

另一个需要注意的事情是,现在你不再需要在构造函数中加上public关键字了:

警告:在0.7.0版本之前,你必须将构造函数的可见性指定为internal或public。

https://docs.soliditylang.org/en/latest/contracts.html?highlight=constructor#constructors


你能帮忙解释一下 memorycalldata 的区别以及它们的使用情况吗? - agentp
1
最简单的解释是: calldata 是一个不可修改、非持久化的区域,用于存储函数参数,并且行为大部分像内存。在声明外部函数的动态参数时必须使用它。memory 是可变的、非持久化的,用于函数声明参数,其生命周期仅限于函数调用,并且应该在声明变量(包括函数参数以及函数逻辑内部)时使用,以便将其存储在内存中(临时)。 - Ahmad Altayeb

4
在返回地址数组的情况下,您可以在返回类型为地址的变量后面声明memory
function getAllPlayers() public view returns(address[] memory){
        return players;
    }

0
Solidity每天都在更新,因此会有一些变化需要您注意。为此,请不断参考更新的Solidity文档。 代码应该是这样的:
contract MyContract {
    string value;

    function get() public view returns (string memory) {
        return value;
    }

    function set(string memory _value) public {
        value = _value;
    }

    constructor() public {
        value = "myValue";
    }
}

或者

contract MyContract {
    string value;

    function get() public view returns (string calldata) {
        return value;
    }

    function set(string calldata _value) public {
        value = _value;
    }

    constructor() public {
        value = "myValue";
    }
}

-3

pragma solidity 0.8.11;

contract Greeter{

    string greeting;

    function greeter(string memory _greeting) public{
        greeting = _greeting;

    }

    function greet() public returns(string memory)
    {
        return greeting;
    }

}

这只是一个代码回答,请考虑添加解释。另外,我建议重用原始代码而不是提供随机示例。 - Yacc

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接