サンプルコントラクトを見ると、「メモリ」を持つメソッドで配列が宣言されている場合とそうでない場合があります。違いは何ですか?
memoryキーワードがない場合、Solidityはstorageで変数を宣言しようとします。
Lead Solidity dev chriseth:「ストレージは、仮想構造を持つ大きな配列と考えることができます...実行時に変更できない構造-これは、契約の状態変数によって決定されます」。
つまり、ストレージの構造は、コントラクトレベルの変数宣言に基づいてコントラクトを作成するときに適切に設定され、今後のメソッド呼び出しでは変更できません。 BUT-そのストレージの内容は、sendTransaction呼び出しで変更できます。このような呼び出しは「状態」を変更するため、コントラクトレベルの変数は「状態変数」と呼ばれます。したがって、変数uint8 storagevar;コントラクトレベルで宣言された値は、uint8(0-255)の任意の有効な値に変更できますが、uint8型の値の「スロット」は常にそこにあります。
memoryキーワードなしで関数で変数を宣言すると、solidityは現在コンパイルされているストレージ構造を使用しようとしますが、予期しない結果が生じる可能性があります。 memoryは、メソッドの実行時に変数用のスペースのチャンクを作成するようにソリディティに指示し、そのメソッドで将来使用するためのサイズと構造を保証します。
memoryはコントラクトレベルでは使用できません。メソッドのみ。
FAQの エントリ「メモリキーワードとは何ですか?何をするのですか?」 を参照してください。ここで引用します:
Ethereum Virtual Machineには、アイテムを格納できる3つの領域があります。
1つは「ストレージ」で、すべての契約状態変数が存在します。すべてのコントラクトには独自のストレージがあり、関数呼び出し間で永続的であり、使用するには非常にコストがかかります。
2番目は「メモリ」で、これは一時的な値を保持するために使用されます。 (外部)関数呼び出しの間で消去され、使用する方が安価です。
3つ目はスタックで、小さなローカル変数を保持するために使用されます。ほぼ無料で使用できますが、保持できる値は限られています。
ほとんどすべてのタイプでは、使用するたびにコピーされるため、格納する場所を指定することはできません。
いわゆる保管場所が重要なタイプは、構造体と配列です。あなたが例えばこのような変数を関数呼び出しで渡すと、メモリ内またはストレージ内にとどまることができる場合、それらのデータはコピーされません。これは、呼び出された関数でそれらの内容を変更でき、これらの変更は呼び出し元に表示されたままであることを意味します。
関係する変数のタイプに応じて、保管場所のデフォルトがあります。
- 状態変数は常にストレージにあります
- 関数の引数は常にメモリ内にあります
- 構造体、配列、またはマッピングタイプのローカル変数はデフォルトでストレージを参照します
- 値型のローカル変数(つまり、配列も構造体もマッピングも)はスタックに格納されます