¿Cómo paso por referencia?

Oct 04 2020

Tengo un par de preguntas.

Primero:

Entonces, en una función, creé una matriz de memoria. Quiero pasar esta memoria por referencia a otra función.

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;
    }

Esto no funciona y dice:

Tipo no válido para argumento en la llamada de función. Se solicitó una conversión implícita no válida de la memoria uint256 [2] al puntero de almacenamiento uint256 [2]. test3 (gio); ^ - ^

¿No es posible?

Segundo

Las funciones internas y privadas son los únicos tipos de funciones que pueden recibir parámetros como tipos de referencia, ¿verdad? Dado que las funciones públicas y externas a las que se llama podrían depender de otra aplicación, otra aplicación no puede pasar parámetros como referencias. ¿De acuerdo?

Tercero .

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

¿Por qué la llamada da como test2resultado:

TypeError: el tipo literal_string "cambiado" no es convertible implícitamente al puntero de almacenamiento de cadena de tipo esperado. str = "cambiado"; ^ --------- ^

Respuestas

1 Ismael Oct 04 2020 at 06:43

Cuando declaras un parámetro como almacenamiento, estás limitando la función para que solo acepte parámetros con ese calificador.

La fase de clasificación storage, memoryy calldataespecifican el lugar donde se encuentran los datos. Puede convertir implícitamente storagea memoryy calldataa memory, pero lo contrario no es posible.

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 {
    
} */

Los tipos de valor como bool, uintXXX, bytesYY, dirección, etc. se pasan por valor. Los tyeps sin valor como estructuras, matrices, cadenas se pasan por referencia.

  • Las funciones que son public, internaly privatepueden utilizar tipos pasan por referencia, pero sólo si son llamadas de un mismo contrato.

  • Funciona publicy externalrecibirá una copia cuando lo llame un usuario habitual de otro contrato.

No sé por qué, pero al menos desde solc 0.3 no estaba permitido.