Wie übergebe ich als Referenz?

Ich habe ein paar Fragen.

Erste:

Also, in einer Funktion habe ich ein Speicherarray erstellt. Ich möchte diesen Speicher durch Verweis auf eine andere Funktion übergeben.

function test2() public returns(uint  a) {
        uint[2] memory gio;
        gio[0] = 100;
        gio[1] = 200;
        test3(gio);
        return gio[0];
    }
    
    
    function test3(uint[2] storage arr) private returns (uint) {
        arr[0] = 35;
    }

Das geht nicht und sagt:

Ungültiger Typ für Argument im Funktionsaufruf. Ungültige implizite Konvertierung von uint256[2]-Speicher in uint256[2]-Speicherzeiger angefordert. test3(gio); ^-^

Ist es nicht möglich?

Zweite

interne und private Funktionen sind die einzigen Funktionstypen, die Parameter als Referenztypen empfangen können, oder? Da aufgerufene öffentliche und externe Funktionen von einer anderen Anwendung abhängig sein könnten, kann eine andere App keine Parameter als Referenzen übergeben. Einverstanden ?

Drittens .

string test;
   
    function test2() public returns(uint  a) {
        test = " awesome ";
        test3(test);
        return 10;
    }
    
    
    function test3(string storage str) private  {
        str = " changed ";
    }

Warum test2führt ein Anruf zu:

TypeError: Type literal_string "changed" ist nicht implizit in den erwarteten String-Speicherzeiger des Typs konvertierbar. str = "geändert"; ^---------^

Antworten (1)

Wenn Sie einen Parameter als Speicher deklarieren, beschränken Sie die Funktion darauf, nur Parameter mit diesem Qualifizierer zu akzeptieren.

Die Qualifizierer storage, memoryund calldatageben an, wo sich die Daten befinden. Sie können implizit storagein memoryund calldatain konvertieren memory, aber das Gegenteil ist nicht möglich.

string public stor = "banana";

function test(string calldata calld) external view {
    string memory memo = "pizza";

    foo(memo, stor);
    foo(calld, stor);  // Creates a copy of calld in memory and passes as parameter
    foo(stor, stor);   // Creates a copy of stor in memory and passes as parameter
    
    foo(memo, stor);
    // foo(memo, memo); // Cannot convert from memory to storage
    // foo(memo, calld); // Cannot convert from calldata to storage
}

function foo(string memory, string storage) internal view {
    
}

/* This fails because you can only use calldata on external functions
function bar(string calldata) internal view {
    
} */

Werttypen wie bool, uintXXX, bytesYY, Adresse usw. werden als Wert übergeben. Nicht-Wert-Typen wie Strukturen, Arrays, Zeichenfolgen werden als Referenz übergeben.

  • Funktionen, die public, internalund sind private, können Typen verwenden, die als Referenz übergeben werden, aber nur, wenn sie von demselben Vertrag aufgerufen werden.

  • Funktioniert publicund externalerhält bei Aufruf durch einen regulären Nutzer eine Kopie von einem anderen Vertrag.

Ich weiß nicht warum, aber zumindest seit Solc 0.3 war es nicht erlaubt.

die Antwort auf die zweite Frage. Sie sagen: Funktionen, die öffentlich, intern und privat sind, können Typen verwenden, die als Referenz übergeben werden, aber nur, wenn sie aus demselben Vertrag aufgerufen werden. Wenn Sie jedoch das Speicherschlüsselwort für den Parameter für die öffentliche Funktion haben, schreit der Compiler und lässt Sie dies nicht tun.
außerdem schreit der Compiler danach: function test(string calldata calld) external view { , calldata location ist hier nicht erlaubt
@NikaKurashvili Solc-Fehler bei der Verwendung von Speicher als Qualifizierer in der öffentlichen Funktion, wie Sie sagten, aber es funktioniert mit dem Speicherqualifizierer. Ich teste mit Solc 0.6.6 und 0.7.2 und beide akzeptieren function test(string calldata calld) external viewohne Vorwarnung.