Gibt es einen Fehler bei der Initialisierung von Bar b in der Funktion foobar?
contract Foo {
struct Bar {
address owner;
uint[] x;
}
Bar[] public bars;
function foobar(address a) public {
Bar storage b = Bar(a, new uint[]) // will that be an array in storage?
bars.push(b)
}
}
storage
Arrays müssen in Solidity nicht initialisiert werden . Nur memory
Arrays müssen vor der Verwendung initialisiert werden.
In Ihrem Fall müssen Sie also nicht initialisieren x
, Bar
solange Sie einem der x
Indizes in Ihrer keinen Wert zuweisen foobar
. Tatsächlich wird die Initialisierung in Ihrem Code ohne Grund Gas verbrauchen.
Der folgende Code funktioniert gut für Ihren Fall:
function foobar(address a) public {
Bar memory b;
b.owner = a;
//When 'b' is pushed to 'bars' array:
// (1) 'b' will be converted from memory to storage.
// (2) And 'x' inside it will be initialized automatically.
bars.push(b);
}
Wenn Sie jedoch auf x zugreifen und einen Wert verschieben müssen, können Sie Folgendes verwenden push
:
function foobar2(address a, uint x0) public {
Bar memory b;
b.owner = a;
bars.push(b);
//Trying: b.x[0] = x0; will generate error. Since, b.x is a memory array that is not initialized!
bars[bars.length - 1].x.push(x0); //This will work fine!
}
Tatsächlich können Sie Ihr Speicherarray immer noch als leeres wie folgt initialisieren:
function foobar3(address a) public {
Bar memory b = Bar(a, new uint[](0)); //Thanks to "James Duffy" for his answer.
bars.push(b);
}
Als letztes ist Folgendes zu erwähnen: Wenn Sie mehrere Werte haben, die Sie in Ihr x
Array einfügen müssen, können Sie dies wie folgt tun:
function foobar4(address a, uint[] _x) public {
Bar memory b = Bar(a, _x);
bars.push(b);
}
Oder wie folgt. Dies verbraucht jedoch mehr Gas:
function foobar5(address a, uint[] _x) public {
Bar memory b;
b.owner = a;
bars.push(b);
Bar storage c = bars[bars.length - 1]; // Get the newly added instance of the storage struct
for (uint i = 0; i < _x.length; i++) {
c.x.push(_x[i]);
}
Überprüfen Sie den vollständigen Code beim netten EthFiddler: https://ethfiddle.com/fQI6Khgz3E
Arbeitsgeige:
https://ethfiddle.com/Yn6fLiAjto
Eine Möglichkeit, dies zum Laufen zu bringen, besteht darin, Ihr Temporär Bar
im Speicher zu erstellen, bevor Sie es auf bars
( Bar memory b
anstatt auf Bar storage b
) verschieben. Solidity kopiert dann automatisch die Strukturdaten aus dem Arbeitsspeicher in den Speicher. Siehe: https://ethereum.stackexchange.com/a/4476/22415 für weitere Details.
Auch new uint[]
ist eine Funktion, die ein Größenargument erfordert, zB new uint[](8)
.
Diese Zeile sollte also vollständig lautenBar memory b = Bar(a, new uint[](8));
Versuche dies:
struct Address {
address[] addressList;
}
function createProposal() public {
address[] memory emptyAddressList;
Address memory _address = Address({
addressList: emptyAddressList
})
}
Muhammad Altabba
Artod
Artod