Pointer auf std::vector element



  • Ich möchte eine Komplexe Klasse an eine vector Liste dieser Klasse anhängen, siehe auch http://www.c-plusplus.net/forum/viewtopic-var-t-is-211805.html

    Jetzt dachte ich mir, dass ich das auch wie folgt machen könnten:

    void DialogFresnelLens::addNewShape()
    {
    	PhaseObjects.resize(PhaseObjects.size() + 1);
    	FresnelPhaseObject = PhaseObjects[0] + (int)(PhaseObjects.size() - 1);
    	FresnelPhaseObject->Settings.PhaseCalcType = Fresnel;
    	FresnelPhaseObject->Description = "Fresnel Lens";
    ...
    

    Ich arbeite also mit der Klasse FresnelPhaseObject wobei diese im Prinzip nur einen Pointer auf den entsprechenden Vector Eintrag darstellt. Beenden ich die Klasse sind die Daten immer noch in der Vector Liste PhaseObjects, welche eine Globale Variable ist.

    Sobald ich jedoch auf FresnelPhaseObject zugreife stürzt das Programm mit einer Zugriffverletzung ab.

    Geht das so nicht?

    Matthias



  • pospiech schrieb:

    Ich möchte eine Komplexe Klasse an eine vector Liste...

    Du solltest dir mal ganz dringend Beispiele ansehen wie man mit vector arbeitet. Jedes Resize, jedes hinzufügen etc. kann den vector vergrößern, und dabei werden seine Daten nicht mehr an der alten Speicheradresse stehen.

    1. Nutze push_back um ein neues Element in einen vector einzufügen (resize hat dort nichts zu suchen).
    2. Nutze niemals Zeiger auf Daten, die unter Umständen nicht mehr dort liegen wohin der Zeiger zeigt.
    3. Komplexe Klassen und Globale Variablen sind meist Indizien von schlechten Design.

    cu André



  • Ich habe es jetzt so gelöst:

    void DialogFresnelLens::addNewShape()
    {
    	FresnelPhaseObject = new PhaseObject;
    	FresnelPhaseObject->Settings.PhaseCalcType = Fresnel;
    	FresnelPhaseObject->Description = "Fresnel Lens";
    }
    
    void DialogFresnelLens::OnButtonSave()
    {
    	PhaseObjects.push_back(FresnelPhaseObject);	
    	close();
    }
    

    wenn ich nun aber die Elemente im vector Array zugreifen dann steht in allen das gleiche drin???

    Matthias



  • Hast du jetzt auf einmal einen vector<PhaseObject*****>? Weist du dem Zeiger FresnelPhaseObject vielleicht noch an irgendeiner anderen Stelle etwas zu und schiebst damit immer denselben Zeiger in deinen Vector?



  • So, gleich wieder mehrere Anmerkungen:

    a) Identische Zeiger [Siehe auch MFK, nur etwas detailierter]

    Ein Vektor enthält immer das was man ihn übergibt (unter nutzung des Copy-Konstruktors). In deinen Fall übergibst du ein Zeiger und dein Vektor kopiert sich den Inhalt desselben. Falls du mehrfach die gleiche Speicheradresse (was deine Problembeschreibung nahelegt) einfügst wirst du jedesmal auf das gleiche Element verweisen.

    b) Wer legt an, wer löscht [a: Globale Objekte]

    Sofern deine Liste tatsächlich ein globales Objekt (was wie schon erwähnt in der Regel auf schlechtes Design hindeutet) ist, solltest du mit Zeigern im Container sehr aufpassen. Wo wird der Speicher den wieder freigegeben? Der Vektor ruft nur den Destruktor von dem Typ auf, für den er Deklariert wurde (Er destruiert hier nur den Zeiger, nicht das Objekt auf den Heap).

    c) Wer legt an, wer löscht [b: Grundlegendes]

    Grundlegend sollte man mit Zeigern in Vektoren meistens aufpassen. Zumindest wenn der Vektor die Datenhaltung übernimmt, und nicht nur als Verweis dient. In deinem Fall wäre ein Smartpointer mit Referenzzählung (wie boost::shared_ptr) wohl deutlich besser geeignet.

    cu André



  • Zu den globalen Variablen. Das sind bei mir alle Geräte die ich ansteuer und die somit nur einmal, und in fast allen Dialogen und Klassen benötigt werden. Zum anderen sind es die 'Dokumente' auf die ich von allen Klassen und Dialogen zugreifen können muss. Das ist hier die vector-Liste.
    Also ingesamt sehr überschaubar, und eine für mich praktikable Lösung.

    Zu der Liste. Ja ich habe sie jetzt als

    vector<PhaseObject*> PhaseObjects;
    

    definiert. Ob das jetzt ein Design Vor- oder Nachteil ist kann ich aber nicht abschätzen.

    Zum Problem: Die Anzeige findet statt über eine Klasse der ich das entsprechende vector Element übergebe, bzw die Nummer und es holt sich dann daraus die Daten

    void DialogBeamView::setComplexBeam(const int number)
    {
    	if ((unsigned int)number < PhaseObjects.size())
    	{
    		ComplexBeamView->setComplexData(& PhaseObjects[number]->ComplexBeam);
    	}
    }
    

    was dann in folgender Funktion landet:

    void widgetAdvancedComplexBeamView::setComplexData(beamshapes * Array)
    {
    	m_ComplexBeam = Array;
    ...
    

    diese widgetAdvancedComplexBeamView wird sowohl in DialogFresnelLens (wo die Daten erzeugt werden), als auch in DialogBeamView (wo die Daten nur angezeigt werden) verwendet.

    Jetzt wurde DialogFresnelLens nicht dekonstruiert, was wie auch immer dazu führte das in DialogBeamView immer exakt das angezeigt wurde was in DialogFresnelLens zuletzt berechnet worden war - selbst wenn die Daten nie im vector Array gespeichert wurden.

    Dekonstruiere ich den DialogFresnelLens, dann zeigt DialogBeamView auch die Daten korrekt an.


Anmelden zum Antworten