# [c++] vector elemente löschen



## Aiju (1. Februar 2006)

Wie kann ich std::vector Elemente ohne invalid pointer Fehler löschen 
Entschuldigt den kurzen Beitrag


----------



## Matthias Reitinger (1. Februar 2006)

Wie wäre es mit der Methode erase?

Entschuldige die kurze Antwort


----------



## Aiju (2. Februar 2006)

Matthias Reitinger hat gesagt.:
			
		

> Wie wäre es mit der Methode erase?
> 
> Entschuldige die kurze Antwort


Das probiere ich ja schon:

```
vector<SFlag*>::iterator it=flags.begin();
for(int i=0;i<j;i++) // Element j löschen
 it++;
flags.erase(it);
```
So ähnlich habe ichs, doch es kommt:

```
glibc detected: invalid pointer 0xXXXXXXX
```


----------



## deepthroat (2. Februar 2006)

Hi.

Um Element i zu löschen, brauchst du den iterator nicht in einer Schleife i-mal weiter setzen, du kannst einfach it += i; setzen.

Möchtest du nur ein Element löschen oder mehrere? Der Iterator wird ungültig wenn du eine modifizierende Operation auf dem Vektor ausführst, d.h. du mußt dir dann einen neuen Iterator besorgen wenn du ein Element gelöscht hast.

Gruß


----------



## Aiju (2. Februar 2006)

Ok, ich habe es so:

```
vector<SFlag*>::iterator it = flags.begin();
  for(int i=0;i<flags.size();i++)
  {
   it++;
   if((robot.x == flags[i]->x) && (robot.y == flags[i]->y))
   {
    flags.erase(it);
    break;
   }
  }
```


----------



## deepthroat (2. Februar 2006)

Das Problem ist, das du den Iterator erhöhst wenn du die Schleife betrittst. Das heißt dein Index i ist immer eins kleiner als der Index des Elementes auf den der Iterator zeigt wenn der Vergleich gemacht wird.

Ich würde es z.B. einfach so machen (ohne den STL Algorithmus find_if zu benutzen):

```
vector<SFlag*>::iterator it = flags.begin();
while (it != flags.end()) {
  if (it->x == robot.x && it->y == robot.y) {
    flags.erase(it); break;
  }
  ++it; /* Hatte ich doch glatt vergessen ...  */
}
```

Gruß


----------



## Aiju (2. Februar 2006)

Wo liegt denn überhaupt der Unterschied zwischen it++ und ++it?


----------



## deepthroat (2. Februar 2006)

Aiju hat gesagt.:
			
		

> Wo liegt denn überhaupt der Unterschied zwischen it++ und ++it?


Oh je.   Wäre evtl. nicht verkehrt wenn du dir erstmal die Grundlagen anschaust.

Das eine ist ein Präinkrementoperator, das andere ein Postinkrementoperator. Es gibt nur einen Unterschied wenn man die Rückgabewerte der beiden Operatoren benutzt. (also für den erase Code völlig unwichtig)

Bsp: 
	
	
	



```
int x = 5;
int pre = ++x; 
int post  = x++;
```
Frage: Was ist der Wert von pre, was ist der Wert von post? Das gleiche Prinzip gilt natürlich auch bei den Iteratoren.

Gruß


----------



## Aiju (2. Februar 2006)

pre = 6
post = 6
Siehe JavaScript für Kids

```
var a=3,b=4,c=5;
(a++ + ++b) * (--c - a);
```
(ist in c anscheinend auch so)


----------



## deepthroat (2. Februar 2006)

Ja, stimmt. 

Allerdings ist nicht definiert was das Ergebnis der Anweisung in C/C++ ist da die Anweisung "undefiniertes Verhalten" auslöst. Bei den meisten Compilern wird allerdings 0 oder 8 herauskommen.

Gruß


----------



## FireFlow (2. Februar 2006)

deepthroat hat gesagt.:
			
		

> Ja, stimmt.
> 
> Allerdings ist nicht definiert was das Ergebnis der Anweisung in C/C++ ist da die Anweisung "undefiniertes Verhalten" auslöst. Bei den meisten Compilern wird allerdings 0 oder 8 herauskommen.
> 
> Gruß



Nein a++ + ++b ist nicht undefined.


----------



## deepthroat (2. Februar 2006)

FireFlow hat gesagt.:
			
		

> Nein a++ + ++b ist nicht undefined.


Aber (a++ + ++b) * (--c - a);

Da wird 2 Mal auf a Bezug genommen wobei a einmal verändert wird und es ist kein Sequence Point im Ausdruck.

Gruß


----------



## blackbirdthefirst (4. Februar 2006)

deepthroat hat gesagt.:
			
		

> Das eine ist ein Präinkrementoperator, das andere ein Postinkrementoperator. Es gibt nur einen Unterschied wenn man die Rückgabewerte der beiden Operatoren benutzt. (also für den erase Code völlig unwichtig)



Der Präinkrementoperator sollte bei Objekten möglichst immer dem Postinkrementoperator
vorgezogen werden, da so zur Laufzeit keine temporären Objekte angelegt werden


----------



## deepthroat (5. Februar 2006)

blackbirdthefirst hat gesagt.:
			
		

> Der Präinkrementoperator sollte bei Objekten möglichst immer dem Postinkrementoperator
> vorgezogen werden, da so zur Laufzeit keine temporären Objekte angelegt werden


Also auf sowas sollte man eigentlich keinen Wert legen, da ein halbwegs gut optimierenden Kompiler die temporären Objekte entfernen wird.

We should forget about small efficiencies, say about 97% of the time: premature
optimization is the root of all evil. -Donald Knuth

Gruß


----------

