vector-elemente referenzieren



  • hi!

    habe hier ein mehr oder weniger grosses problem:
    einen vektor mit x elementen und einen zweiten, dessen elemente auf je ein element des ersten vektors zeigen.
    Das funktioniert bis zu dem punkt, bis ich dem ersten vektor ein neues element hinzufüge, per insert oder push_back meinetwegen, denn dann zeigen die elemente des zweiten vektors auf undefiniertes zeug, aber nicht mehr auf die elemente des ersten vektors. das erscheint insofern logisch, als das vector den speicher selbst verwaltet.

    nun zur frage: wie kann ich effizient auf elemente eines vectors zeigen, der sich bei laufzeit veraendert?



  • Must Du zwingend auf die Vectorelemente zeigen, oder auf die Elemente im Vector? (öh?)

    vector<Element> vector1;
    vector<Element*> vector2;
    Element element1;
    vector1.push_back( element1 );
    vector2.push_back( &element1 );
    

    Ansonsten bleibt Dir noch, bei Änderungen vector2 zu aktualisieren.

    Oder Du nimmst einen Container wo die Iteratoren gültig bleiben, zB ne list, falls das möglich ist.



  • eigentlich brauch ich nur die elemente selbst.
    dein bsp. hatte ich auch probiert, da hat er aber das gleiche gemacht.

    änderungen zu aktualisieren war auch ne ueberlegung, faellt aber raus, weil da zuviel zeit drauf geht.
    eine list ist n guter plan, aber auch nicht so stark fuer direkte indizierung, die ich zwingend und performant brauhe.

    hab jetz als uebergangsloesung in beiden vektoren zeiger auf die vermeintlichen elemente genommen, so in etwa:

    vector<Element*> vec1;
    vector<Element*> vec2;
    vec1.push_back(new Element());
    vec2.push_back(vec1.back());
    

    ist zwar etwas risky, aber looft schonmal.

    bin trotzdem offen fuer weitere vorschlaege 😉



  • japanitrat schrieb:

    vector<Element*> vec1;
    vector<Element*> vec2;
    vec1.push_back(new Element());
    vec2.push_back(vec1.back());
    

    ist zwar etwas risky, aber looft schonmal.

    Was ist denn da risky?
    Wenn Du konsequent in beiden Vectoren einfügst und entfernst, stimmt der Index überein. Du musst halt drauf achten, dass Du immer beide gleich änderst.
    Ev. eher so:

    vector<Element*> vec1;
    vector<Element*> vec2;
    Element* e1 = new Element()
    vec1.push_back( e1 );
    vec2.push_back( e1 );
    

    Oder mach ne kleine Funktion, wenn das geht:

    vector<Element*> vec1;
    vector<Element*> vec2;
    vectors_push( Element* elem )
    {
        vec1.push_back( elem );
        vec2.push_back( elem );
    }
    //...
    vectors_push( new Element() );
    


  • na risky von daher, dass zeiger generell risky sind :>
    das ist ja alles sowieso nochmal in klassen verpakkt, die da eigentlich drauf aufpassen sollen. wenn ich in einem vektor ein element per delete freigebe, muss es sofort aus dem zweiten vektor auch raus, nich dass noch wer drauf zugreift, obwohl das teil garnicht mehr existiert 😉

    ich find zeiger generell unhübsch, aber ohne gehts wohl nicht... :>



  • Hm, ja das mit den Zeigern entfernen ist irgendwie unschön.
    "is alles in Klassen verpackt" meinst Du beide Vectoren in der selben Klasse?
    Wie sieht denn das Programm ringsum aus?
    Brauchst Du wirklich 2 gleiche Vectorten oder würde einer reichen?
    Du kannst ihn ja eventuell per Referenz rumreichen..



  • naja, stell dir vor, der erste vektor klemmt in einer klasse, die sozusagen als datenbank fungiert.
    der zweite vektor gehört zu einer anderen klasse, die mit den elementen der ersten klassen herumspielt (also zugriff auf die einzelnen elemente der ersten bekommen muss), aber keinen direkten zugriff auf den ersten vektor hat.

    die zweite lagert dann alle elemente der ersten plus zusatzinformationen, wie z.b. datum. im konkreten versucht die zweite klasse eine uhr mit queue zu sein. d.h. alle elemente bekommen ein startdatum und eine intervall-spezifikation. die uhr sortiert den zweiten vektor in der reihenfolge der startdaten und addiert nach vollzogenem start den intervall drauf und sortiert wieder ein .. (verwirrend schreib ich glaube ich 😉 ), wobei sie dabei die datumsinformation auch in dem ursprungselement selbst speichert. der sinn dieser klasse besteht darin, eine bool-flag in dem fuer einen bestimmten zeitraum an einem bestimmten zeitpunkt zu aktivieren und wieder zu deaktivieren

    der benutzer greift nie auf die zweite klasse zu, nur auf die erste und schaut, ob das gesuchte element gerade true oder false ist.

    aehhh ... ja. verwirrend, aber alles kann ich auch nicht verraten :>



  • japanitrat schrieb:

    aehhh ... ja. verwirrend...

    😕 Allerdings..



  • ok, vielleicht so:

    es gibt eine klasse, nennen wir sie DB, die hält x elemente vom typ ITEM.
    das ITEM wiederum besitzt die eigenschaften LAUNCHTIME, LAUNCHFLAG, LAUNCHINTERVAL und LIFETIME.

    der nutzer soll nun ein beliebiges ITEM von DB anfordern und schauen, ob LAUNCHFLAG true oder false ist.

    parallel dazu in einem anderen thread fungiert die klasse CLOCK. Diese kennt alle ITEMs aus DB und prüft permanent ob die LAUNCHTIME eines ITEMs überschritten wurde. wenn dem so ist, wird LAUNCHFLAG dieses ITEMs für den zeitraum LIFETIME auf true gesetzt. ist LIFETIME überschritten, wird LAUNCHFLAG wieder auf false gesetzt, LAUNCHINTERVAL mit LAUNCHTIME addiert und neu in die CLOCK-queue einsortiert.

    macht der nutzer nun zu genau dem richtigen zeitpunkt auf DB eine anfrage zu ITEM, bekommt er ein true (LAUNCHFLAG) zurueck, andernfalls ein false.

    ist das einleuchtender? :p



  • Ich unterstelle mal, dass CLOCK diesen anderen vector< ITEM*> enthält, um seinen 'setze LAUNCHFLAG'-Job zu tun. Wenn dem so ist, wäre es soch einfacher, wenn DB einen vector< ITEM > enthält (keine Zeiger) und CLOCK einen Zugriff auf DB bekommt, der diesen vector< ITEM > von DB bereitstellt.

    Das ganze muss natürlich sauber per Mutex geschützt werden.

    Vorteil: nur ein vector< ITEM >, die Verwaltung übernimmt DB und CLOCK hält keine Daten doppelt.
    Konsequenz: in CLOCK muss ein ITEM irgendwie identifizierbar sein, für die CLOCK-Queue.

    Hat jedes ITEM eine eindeutige Id? Wäre doch für die Abfrage eines Clients auch notwendig - oder?

    Gruß
    Werner



  • jojo, jedes ITEM hat eine unique id.

    die CLOCK-queue ist so gedacht, dass die ITEMs auf basis ihrer LAUNCHTIME sortiert werden. ich prüfe damit im spaeteren verlauf nur noch das erste Element.
    desweiteren wollte ich diese beiden prozesse, also DB und CLOCK klar voneinander trennen und nicht mit der CLOCK in dem DB-vector rumspielen.

    hmhm, ich bin unschluessig....



  • japanitrat schrieb:

    jojo, jedes ITEM hat eine unique id.

    Das ist schon mal gut.

    japanitrat schrieb:

    die CLOCK-queue ist so gedacht, dass die ITEMs auf basis ihrer LAUNCHTIME sortiert werden. ich prüfe damit im spaeteren verlauf nur noch das erste Element.
    desweiteren wollte ich diese beiden prozesse, also DB und CLOCK klar voneinander trennen und nicht mit der CLOCK in dem DB-vector rumspielen.

    Wenn CLOCK irgendwie das LAUNCHFLAG im ITEM der DB setzt, was später dann vom Nutzer/Client der DB abgefragt wird, bleibt Dir nichts anderes übrig.
    Dann besser eine saubere Schnittstelle für DB implementieren, als mit einem Pointer ITEM* irgendwas ändern, was vielleicht gar nicht mehr da ist, oder gerade parallel dazu von einem anderen Thread geändert wird.

    Oder Du denkst darüber nach die CLOCK-Funktonalität nach DB zu verlagern und CLOCK produziert nur noch den Trigger, der dann diese Funktionalität aufruft. .. oder so

    Gruß
    Werner


Anmelden zum Antworten