Wie initialisiert man ein leeres Array innerhalb einer Struktur?

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)
    }

}

Antworten (3)

storageArrays müssen in Solidity nicht initialisiert werden . Nur memoryArrays müssen vor der Verwendung initialisiert werden.

In Ihrem Fall müssen Sie also nicht initialisieren x, Barsolange Sie einem der xIndizes 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 xArray 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

Herzlich willkommen. Und danke an Georgios Konstantopoulos und Loom Network: medium.com/loom-network/…
Nach dem Aufruf von foobar, foobar2 oder foobar3 erhalte ich den Wert von bars[0] == {owner: address } ohne Eigenschaft x überhaupt!!! Es wird komplett ignoriert. Wie ist es möglich? Was mache ich falsch?
Ich habe herausgefunden, warum dies geschieht. Benötigen Sie einen separaten Getter, um Arrays von Strukturen wie getXFromBar zu erhalten

Arbeitsgeige:

https://ethfiddle.com/Yn6fLiAjto

Eine Möglichkeit, dies zum Laufen zu bringen, besteht darin, Ihr Temporär Barim Speicher zu erstellen, bevor Sie es auf bars( Bar memory banstatt 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));

Ich verstehe! Also kann ich der Struktur beim Initialisieren kein Array mit dynamischer Größe zuweisen?
schon Antworten?

Versuche dies:

struct Address {
    address[] addressList;
}

function createProposal() public {
    address[] memory emptyAddressList;
    Address memory _address = Address({
       addressList: emptyAddressList
    })
}