Солидность - начальное сопоставление структуры можно игнорировать

Я обнаружил, что при инициализации структуры мы можем просто игнорировать тип сопоставления, например:

pragma solidity ^0.4.0;

contract C{
  struct Person{
    string name;
    mapping(address=>int) map;
    string[] nickNames;
    int age;
  }

  function init() constant returns (string, int){
    string[] memory nickNames = new string[](1);
    nickNames[0] = "cat1099";

    Person memory p = Person("Jack", nickNames, 23);

    return (p.name, p.age);
  }
}

В служебном документе я нашел только примечание к коду, в котором говорится: «Мы опускаем тип сопоставления». После поиска на этом сайте здесь кто-то сказал, что:

Сопоставления можно рассматривать как хеш-таблицы, которые виртуально инициализируются таким образом, что каждый возможный ключ существует и отображается на значение, байтовое представление которого состоит из нулей: значение типа по умолчанию. Однако на этом сходство заканчивается: данные ключа на самом деле не хранятся в отображении, только его хэш keccak256 используется для поиска значения.

Означает ли это, что solidty не может инициализировать сопоставление в структуре, поэтому просто игнорируйте его. Может ли кто-нибудь прояснить это, поскольку официального объяснения этому нет?

Ответы (1)

Как разработчик, вы можете рассматривать сопоставление как все возможные пары ключ/значение со значениями, инициализированными 0, false, пустым массивом и т. д. в зависимости от типа. Нет необходимости инициализировать явно. Они просто есть.

Сюда входят сопоставления внутри структур. Значения останутся нулевыми, пока не будут явно установлены.

Могут быть полезны сопоставления внутри структур, а также сопоставления структур или и то, и другое, как показано ниже.

Ключи не хранятся в сопоставлениях.

Учитыватьmapping(uint => address) numberedAddresses;

Ключ ( uint) хешируется, чтобы найти «слот», и addressсохраняется в этом слоте. Сам ключ не сохраняется. Единственный способ получить сопоставленное значение — это вызвать его обратно, используя знание ключа:

numberedAddress[key];

Есть некоторые последствия для ознакомления. Невозможно перечислить ключи в отображении. Точно так же невозможно их сосчитать. Мы могли бы сказать, что «существуют все возможные ключи» во всех случаях.

Если кто-то хочет перечислить ключи, которые мы фактически установили (общие), тогда нужно хранить сами ключи в другом месте. Здесь есть несколько примеров шаблонов, например Mapped Structs with Index, которые помогают предотвратить повторное изобретение вещей. Существуют ли хорошо решенные и простые шаблоны хранения для Solidity? .

Пример ниже предназначен для игры в Remix. Вы получите все 0 результатов для любого ключа от геттеров, пока не установите что-то явно. Последние две функции показывают, как работать с отображением, хранящимся внутри структуры.

Надеюсь, это поможет.

pragma solidity ^0.4.6;

contract Mappings {

    // For all new structs, all answer flags at all key locations are false until set. 

    struct UserStruct {
        uint balanceOf;
        bool isActive;
        mapping(uint => bool) answerFlags;
    }

    // Key => Struct. All keys initialize to 0.
    // Query any unset Key and get balanceOf == 0 and isActive == false.

    // (More common to use address => struct for "users") 

    mapping(uint => UserStruct) public userStructs;

    // Key => Bool. All keys initialize to false
    // Query any unset key and get false.

    mapping(uint => bool) public addressFlags;

    // Set values in storage

    function setUserStruct(uint key, uint balanceOf, bool isActive) public returns(bool success) {
        userStructs[key].balanceOf = balanceOf;
        userStructs[key].isActive  = isActive;
        return true;
    }

    function setAddressFlag(uint key, bool flagAddress) public returns(bool success) {
        addressFlags[key] = flagAddress;
        return true;
    }

    // Mapping inside a struct

    function getUserAnswerFlag(uint userStructKey, uint userAnswerKey) public constant returns(bool answerFlag) {
        return userStructs[userStructKey].answerFlags[userAnswerKey];
    }

    function setUserAnswerFlag(uint userStructKey, uint userAnswerKey, bool setValue) public returns(bool success) {
        userStructs[userStructKey].answerFlags[userAnswerKey] = setValue;
        return true;
    }

}