Ethereum Solidity: Memory vs Storage & Как да инициализираме масив в структура

В телеграмата на Loom Network (която наброява около 8 000 членове!) Хората задават въпроси по различни теми като пътната карта на Loom, теоретичните въпроси на blockchain и Ethereum и отстраняването на неизправности в Solidity.

Беше зададен конкретен въпрос, който включваше инициализиране на масив вътре в структура. Човекът, който го попита, след това предостави кода си, чудейки се защо не работи. Не можах да измисля отговор на върха на главата си, затова реших да поговоря накратко по тази тема в пост.

Неработещият код можете да намерите по-долу. Съветвам ви да опитате сами да намерите решение (вие през цялото това време практикувате CryptoZombies, нали?).

Прочетете, за да намерите отговора.

Трябва да се отбележи, че в горната скрипка паметта на ключовите думи е необходима при деклариране на променливата стая. Ако беше деклариран като Room room, компилаторът ще върне следната грешка:

TypeError: Type struct StructArrayInitWrong.Room паметта не е конвертируемо неявно в очаквания тип структура StructArrayInitWrong.Room указател за съхранение.

Някаква теория

Променливите за съхранение на договора са тези, които определят състоянието на вашия договор и се променят само чрез callTransaction разговори [1].

променливите на паметта са временни променливи, които съществуват само вътре в извикващата функция (те не могат да бъдат декларирани извън една). Те се изтриват, след като функцията излезе и обикновено са по-евтини за използване от променливите за съхранение - повече подробности за разходите за газ тук.

Нека разгледаме пример, за да разберем как променлива за съхранение може да се използва във функция, за да повлияе на състоянието на договора.

В следната скрипка копие на x се предава в g () като и по този начин променливата на състоянието x ще остане непроменена след изпълнението (това е причината да използваме чистата ключова дума.

От друга страна, y в h () се декларира като съхранение, което означава, че x се предава чрез препратка. В резултат променливата на състоянието x се променя след извикването в h ().

Можете да тествате резултата, като се обадите на f () и след това да проверите стойността на y [2]. Въпреки че g () се извиква след h (), тя не променя стойността на променливата на състоянието.

Достатъчно теоретизиране, нека да стигнем до отговора на първоначалния въпрос.

Тъй като не можем да инициализираме масива на играчите при инициализиране на структурата, ние сме принудени да правим това на стъпки:

  1. Инициализирайте структурата на стаята до стойности по подразбиране с празен масив играчи - както е описано тук и в тази скрипка.
  2. Избутайте стаята към масива от стаи.
  3. Натиснете msg.sender към масива с играчи в последната стая (rooms.length-1 винаги се отнася до последния елемент в масива).

Работен код Fiddle по-долу:

Номерът тук е, че новият адрес [] (0) разпределя памет за празен масив от адреси. След инициализацията стаята се добавя към стаите и вече е част от променлива за съхранение. Това ни позволява да работим с масиви плейъри и да натискаме стойности към него.

Забележка: Ако направихме нов uint [] (8), ще получим масив от 8 нули. Можете да го тествате в тази скрипка.

Това е всичко за днес, надявам се, че изчистихме някои недоразумения по отношение на съхранението / паметта и как да ги използваме във вашите функции. Уведомете ни за вашите въпроси по нашия канал Telegram и ако на тях не могат да се отговорят в няколко съобщения, ние ще посветим публикация в него (или може би урок за CryptoZombies!)

Loom Network е платформата на blockchain, избрана за сериозни разработчици на dapp - Universal Layer 2, която предоставя на разработчиците инструментите, от които се нуждаят, за да изграждат функционални, насочени към потребителите, днес.

Нови за Loom? Започни тук.

Искате да заложите своите маркери LOOM и да помогнете за сигурната Loom Network? Разберете как.

И ако ви е харесала тази статия и искате да останете в цикъла, продължете напред и се запишете за нашия личен пощенски списък.