array in struct zur laufzeit initialisieren


  • Mod

    proty schrieb:

    Ich hab jetzt eine Funktion zum erstellen einer neuen ABC instanz geschrieben, die sieht so aus:

    ABC create(int capacity)
    {
       ABC* rb = new ABC(capacity);  
       return *rb;
    }
    

    und in der main ruf ich das dann so auf:

    ABC rb = create(256);
    

    LOL, wozu ist das denn gut? Einen Konstruktor in einer create Funktion kapseln?

    Mach doch einfach

    ABC rb(capacity);
    

    Dann bekommst du auch keine Probleme wegen dem fehlendem delete.

    schreibe, läuft das mit beliebigen werten für MAX (bzw. mit allen die ich getestet hab), das kann doch nciht stimmen oder?

    Kann schon sein, ist eben undefiniert. Wobei mich das schon wundert, dass du keinen Segfault bekommt. Hast du nie MAX>100000 probiert?

    Sprich das Verhalten ist nicht definiert und du solltest vorher prüfen, wie groß dein Array ist.

    sizeof(rb.array) liefert im obigen beispiel 8...?

    Klar, rb.array ist doch nur ein Pointer und 8 ist seine Größe. sizeof zählt schließlich nicht wie groß das ist, worauf der Pointer zeigt.

    Mach so etwas:

    struct ABC
    {
       int* array;
       size_t size;
       ABC(size_t size) : array(new int[size]), size(size) {}
       ~ABC() {delete[] array;}
    };
    

    Wobei dies darauf hinausläuft, dass wir jetzt nach und nach (den oben vorgeschlagenen) std::vector nachprogrammieren.



  • proty schrieb:

    Ich hab jetzt:

    struct ABC
    {
       int* array;
       ABC(size_t size) : array(new int[size]) {}
       ~ABC() {delete[] array;}
    };
    

    und in der main will ich dann eine Variable vom Typ ABC anlegen:

    ABC* rb = new ABC(capacity);
    

    🙄
    - Verletzung der Dreierregel bei struct ABC
    - Der Konstruktor sollte mit explicit versehen werden.
    - rb ist keine Variable vom Typ ABC. Es ist eine Variable vom Typ ABC*, also ein Zeiger.
    - Es gibt nur einen guten Grund, warum Du hier auf std::vector<> verzichten solltest: Zu Lernzwecken.
    - Es könnte soooooo einfach sein:

    struct ABC
    {
      std::vector<int> feld;
    
      explicit ABC(int groesse)
      : feld(groesse)
      {}
    };
    
    int main()
    {
      ABC obj (42);
      obj.feld[33] = 99;
      return obj.feld.size()==42 ? 0 : 1;
    }
    

    Man beachte die geringe Zahl an Sternchen in obigem Code: 0.

    Schreib nicht einfach irgend ein Zeug, ohne zu wissen, was da eigentlich passert. Lerne die Sprache richtig. Lies ein Buch dazu. etc etc etc


  • Mod

    krümelkacker schrieb:

    🙄
    - Verletzung der Dreierregel bei struct ABC

    Das musst du aber mir ankreiden, weil ich ihm das so vorgegeben habe. Ich wollte nicht zu viel auf einmal bringen, sondern erst einmal Konstruktoren zeigen (die er offensichtlich noch nicht kannte). Und ich hatte eigentlich erwartet, dass er gleich, wie von mir vorgeschlagen, einen vector nimmt, anstatt die Idee weiter zu verfolgen.



  • Okay danke, dann weiß ich was die größe angeht bescheid.

    Das ist ganz böse. Du erstellst im dynamischen Speicher ein Objekt, kopierst es und vergisst den Zeiger.

    Was meinst du damit?

    Ich hab die create funktion jetzt nochmal angepasst:

    ABC create(int capacity)
    {
       ABC rb(capacity);  
       return rb;
    }
    

  • Mod

    proty schrieb:

    Ich hab die create funktion jetzt nochmal angepasst:

    ABC create(int capacity)
    {
       ABC rb(capacity);  
       return rb;
    }
    

    Das ist prinzipiell ok, wenn man es richtig macht, aber:
    - Wozu soll das gut sein?
    - Wie krümelkacker schon sagte, habe ich in meinem Beitrag nicht alle nötigen Funktionen einer Klasse implementiert, die Daten dynamisch verwaltet. Unter anderem habe ich den Kopierkonstruktor weggelassen, daher ist das was hier geschieht nicht in Ordnung.

    Beantworte aber erst einmal die Fragen die dir hier im Thread gestellt wurden.



  • Es wurde ja schon darauf hingewiesen

    struct ABC
    {
       std::vector<int> values;
       ABC(size_t size): array(size){}
    }; 
    
    int main()
    {
      // ABC* abc = new ABC(256);
      // abc->values[260];
      // tu so
      ABC abc(256);
      abc.values.at(260); // jetzt sagt dir dein Programm auch, dass das nicht geht
      return 0;
    }
    

    edit: häm.. da hing ich wohl ein wenig zu lang in der Leitung...



  • - Wozu soll das gut sein?

    Ich will eine create funktion schreiben, da, wenn das mal richtig tut, weitere member in die struct kommen und die dann in der create funktion benutzt werden.

    wenn ich

    struct ABC
    {
       vector<int> array;
       ABC(size_t size): array(size){}
    };
    

    schreibe, sagt der compiler bei sowas

    rb.array[i]
    

    dass struct ABC kein meber array hat...?



  • proty schrieb:

    Das ist ganz böse. Du erstellst im dynamischen Speicher ein Objekt, kopierst es und vergisst den Zeiger.

    Was meinst du damit?

    Dass du das soeben dynamisch erstellte Objekt kopierst, wogegen nichts einzuwenden ist, aber dann den für das anschließende delete nötigen Zeiger dir nicht merkst. Du sollst nach Möglichkeit immer ein delete auf ein new folgen lassen. Nur in ganz wenigen Ausnahmefällen könnte man es aus Geschwindigkeitsgründen weg lassen.


  • Mod

    proty schrieb:

    - Wozu soll das gut sein?

    Ich will eine create funktion schreiben, da, wenn das mal richtig tut, weitere member in die struct kommen und die dann in der create funktion benutzt werden.

    Es kann Fälle geben, wo dies sinnvoll ist, aber ich gehe sehr stark davon aus, dass dies keiner davon ist.

    wenn ich

    struct ABC
    {
       vector<int> array;
       ABC(size_t size): array(size){}
    };
    

    schreibe, sagt der compiler bei sowas

    rb.array[i]
    

    dass struct ABC kein meber array hat...?

    Das sollte nicht sein. Gibt's andere Fehlermeldungen? Womöglich vector nicht eingebunden?



  • SeppJ schrieb:

    proty schrieb:

    - Wozu soll das gut sein?

    Ich will eine create funktion schreiben, da, wenn das mal richtig tut, weitere member in die struct kommen und die dann in der create funktion benutzt werden.

    Es kann Fälle geben, wo dies sinnvoll ist, aber ich gehe sehr stark davon aus, dass dies keiner davon ist.

    Gibts dann eine andere möglichkeit dem nicht vollständig definierten array im struct int array[] beim initialiseren einer neuen struct variable die länge zuzuweisen?

    wenn ich

    struct ABC
    {
       vector<int> array;
       ABC(size_t size): array(size){}
    };
    

    schreibe, sagt der compiler bei sowas

    rb.array[i]
    

    dass struct ABC kein meber array hat...?

    Das sollte nicht sein. Gibt's andere Fehlermeldungen? Womöglich vector nicht eingebunden?

    die fehlermeldung is

    error: invalid conversion from ‘int*’ to ‘long unsigned int’
    und
    error: initializing argument 1 of ‘std::vector<_Tp, _Alloc>::vector(size_t, const _Tp&, const _Alloc&) [with _Tp = int, _Alloc = std::allocator<int>]’



  • mein ganzer quellcode sieht so aus:

    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    struct ABC
    {
       vector<int> array;
       ABC(size_t size) : array(new int[size]) {}
    
    };
    
    ABC create(int capacity)
    {
       ABC rb(capacity);
    
       return rb;
    }
    
    int main()
    {
       ABC rb = create(256);
       cout << sizeof(rb.array) << endl;
       for (int i = 0; i < 256; ++i)
       {
          rb.array[i] = i+1;
          cout << rb.array[i] << endl;
       }
       return 0;
    }
    


  • 🙂

    probiers mal mit:

    Zeile 9: ABC(size_t size) : array(size) {} // damit wird die Arraygröße zur Erstellungszeit festgelegt
    
    Zeile 23: cout << rb.array.size() << endl;
    

    Und bitte mach mal den Quatsch mit der create-Funktion weg.



  • Also so:

    struct ringbuffer
    {
       vector<int> array;
       ringbuffer(size_t size) : array(size) {}
    };
    
    int main()
    {
       ringbuffer rb(256);
       cout << rb.array.size() << endl;
       for (int i = 0; i < 256; ++i)
       {
          rb.array[i] = i+1;
          cout << rb.array[i] << endl;
       }
       return 0;
    }
    

    Tausend Dank euch allen 🙂


Anmelden zum Antworten