Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

14.02.2015, 16:19

Element aus Vector entfernen

Gudden tach liebes Forum

ich kämpfe immoment mit einer for schleife die elemente aus einem Vector "sicher" löchen soll!

Das ist das gute Stück

C-/C++-Quelltext

1
2
3
4
5
6
7
    for (vector<CField*>::iterator i = Fields.begin(); i != Fields.end(); i++)
    {
        if (//bla bla)
        {
            
        }
    }


Soweit so gut jedoch möchte ich nun wenn die if-abfrage korrekt war das entsprechende Element löschen!

Das habe ich mir dann zunächst so gedacht:

C-/C++-Quelltext

1
2
3
4
5
6
7
for (vector<CField*>::iterator i = Fields.begin(); i != Fields.end(); i++)
    {
        if (//bla bla)
        {
            Fields.erase(i);
        }
    }

So.... Das Programm stürzt ab und zeigt mir diese Meldung:
Expression: list iterator not incrementable.
Naja das interpretiere ich so dass ich anstatt den eintrag in der Liste nun den Interator gelöscht habe
und ich ihn nun nicht mehr hochzählen kann.... korregiert mich bitte falls ich falsch liege.

Zusätzlich dazu möchte ich auch die Zeiger der elemente löschen. Jedoch klappt dies nicht
da ich wenn ich das nächte mal auf die Liste zugreiffe wieder auf die Nase fliege da dann der enstsprechende
iterator Zeiger = NULL ist.

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
#define SAFE_DELETE(X) {if (X != NULL) {delete(X);X=NULL;}}

for (vector<CField*>::iterator i = Fields.begin(); i != Fields.end(); i++)
    {
        if (//bla bla)
        {
                        Fields.erase(i);
            SAFE_DELETE(*i);
        }
    }


Ich glaube ich verstehe meine Fehler weiß es leider nur nicht besser....
bitte helft mir

Danke Urprimat
Most good programmers do programming not because they expect to get paid or get adulation by the public, but because it is fun to program.

Linus Torvalds

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

2

14.02.2015, 16:23

1) Wieso muss der vector Pointer auf dynamisch erzeuge CField Objekte enthalten? Kann es nicht einfach direkt ein std::vector<CField> sein?
2) Wenn es sein muss, dann am besten einfach std::vector<std::unique_ptr<CField>>.
3) Diese Namenskonvention vor Klassennamen ein C zu packen war in den 90ern schon out... ;)
4) SAFE_DELETE ist sinnlos, da ein delete nullptr völlig ok ist (tut einfach nix).

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

3

14.02.2015, 16:27

Der Iterator ist nach dem löschen nicht mehr gültig. Die Funktion erase gibt einen Iterator zurück. Das ist der neue aktuelle Iterator. Den musst du deiner Iteratorvariable zuweisen.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

4

14.02.2015, 16:28

im Grunde ist der Vector ein 9*9 großes "Schachbrett".
Jedes Feld besteht aus der Klasse CField.



C-/C++-Quelltext

1
2
3
4
5
                for (int x = 1; x <= 9; x++)
        {
            Fields.push_back(new CField(x, y));
            EditBoxID++;
        }


Ich dachte mir das ich dadruch Performance spare wenn ich nur eine Speicheradresse übergebe..... oder ist das Falsch?
Most good programmers do programming not because they expect to get paid or get adulation by the public, but because it is fun to program.

Linus Torvalds

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

5

14.02.2015, 16:31

@dot: Hättest Du nicht wenigstens die eigentliche Frage beantworten können?

Zusätzlich zu Schorschs Antwort sei angemerkt, dass ein "for" hier nicht funktionieren wird.

Performance sparst Du effektiv vermutlich gar keine, sondern hast stattdessen Objekte im Heap erzeugt, die nicht hätten im Heap erzeugt werden müssen.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

6

14.02.2015, 16:31

Der Iterator ist nach dem löschen nicht mehr gültig. Die Funktion erase gibt einen Iterator zurück. Das ist der neue aktuelle Iterator. Den musst du deiner Iteratorvariable zuweisen.



Achwas aso einfach wie folgt:

C-/C++-Quelltext

1
i = Fields.erase(i);
Most good programmers do programming not because they expect to get paid or get adulation by the public, but because it is fun to program.

Linus Torvalds

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

7

14.02.2015, 16:34

Wenn Du das machst, überspringst Du ein Feld (das nach dem gelöschten Element) wegen dem i++ im for.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

8

14.02.2015, 16:39

Oh ja macht sinn. Jetzt verstehe ich was du damit meintest das for hier keinen sinn macht
ich habe nun eine while schleife erstellt. ist das so besser?!

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
vector<CField*>::iterator i = Fields.begin();
    while (i != Fields.end())
    {

        if ((*i)->GetFieldValue() != 0)
        {
            i = Fields.erase(i);
        }
        else
        {
            i++;
        }
            

    }
Most good programmers do programming not because they expect to get paid or get adulation by the public, but because it is fun to program.

Linus Torvalds

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

9

14.02.2015, 17:01

Ja.
Ergänzend möchte ich mal noch auf das Schlüsselwort "auto" hinweisen, was für Zeile 1 angebracht wäre.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

10

14.02.2015, 17:04

Wenn du nun die Fields direkt im vectors speicherst anstatt es mit Zeigern zu machen wäre es noch besser ^^
(Außer du hast da was mit Polymorphie am laufen, aber das sieht hier nicht so aus)
Du kannst das übrigens auch so machen:

C-/C++-Quelltext

1
2
3
4
for(auto i = Fields.begin();i != Fields.end();)
{
//...
}

Werbeanzeige