Содержание

Местоположение данных в Solidity

Каждый сложный тип, то есть массив (array) или структура (struct), имеет дополнительную аннотацию — местоположение данных (“data location”), которая указывает, где он хранится (в memory или в storage). В зависимости от контекста всегда есть значение по умолчанию. Но это значение можно изменить используя storage или memory. Для параметров функции (включая возвращаемые параметры) значение по умолчанию memory. Для локальных переменных — storage.

Также есть третье местоположение — calldata. Это неизменяемая, непостоянная область, где хранятся аргументы функции. Параметры функции (не возвращаемые параметры) external-функции хранятся в calldata и ведут себя в основном как memory.

Местоположения данных важны, потому что от них зависит, как ведут себя присвоения: присвоения между storage и memory, а также присвоение глобальной переменной всегда создает независимую копию. Присвоение локальной переменной создает ссылку, и эта ссылка всегда указывает на глобальную переменную, даже если последняя в это время изменена. Присвоение ссылочного типа в memory другому ссылочному типу memory не создает копию.

pragma solidity ^0.4.0;

contract C {
    uint[] x; // местоположение x — storage

    // местоположение memoryArray — memory
    function f(uint[] memoryArray) public {
        x = memoryArray; // копирует весь массив в storage
        var y = x; // создает ссылку, местоположение y — storage
        y[7]; // возвращает 8-ой элемент
        y.length = 2; // изменяет x через y
        delete x; // очищает массив, также изменяет y
        // Следующий код не работает; здесь необходимо было бы создать новый временный
        // массив без имени в storage, но storage выделяется "статично":
        // y = memoryArray;
        // Это тоже не работает, поскольку он "перезагружает" указатель,
        // но нет местоположения, на которое он мог бы указывать.
        // delete y;
        g(x); // вызывает g и передает ссылку на x
        h(x); // вызывает h и создает независимую временную копию в memory
    }

    function g(uint[] storage storageArray) internal {}
    function h(uint[] memoryArray) public {}
}

Резюме:

Принудительное местоположение данных:

  • параметры (не возвращаемые) external-функций: calldata
  • глобальные переменные: storage

Местоположение данных по умолчанию:

  • параметры функций (в том числе возвращаемые): memory
  • все другие локальные переменные: storage
Материал был полезен? Поделитесь в соц. сетях:
Логотип echain.ru

Добавить комментарий

Ваш e-mail не будет опубликован.