2017-09-11 3 views
7

I understand (at least I think I do) dass Zeiger als zufällige STL-Iteratoren verwendet werden können.STL-Vektor löschen über Zeiger

Warum wird der folgende Code nicht kompiliert, wenn ich den Zeiger nicht auf einen Iterator umsetze?

vector<int> v{1, 2, 3}; 
v.erase(&v[0]); 
+12

Warum denken Sie, dass ein Zeiger auf das Element derselbe wie ein Iterator ist ('std :: vector :: iterator')? – NathanOliver

+1

Welchen Fehler bekommen Sie? –

+6

Während Iteratoren mithilfe von Zeigern implementiert werden konnten, ist ein Zeiger nicht automatisch ein Iterator. –

Antwort

12

Sie können Zeiger auf Algorithmen wie std::sort, std::find oder std::copy passieren. Dies sind Vorlagen, die für alles konfigurierbar sind, das als geeigneter Iterator fungiert.

Dies bedeutet nicht, dass verschiedene Iteratoren notwendigerweise zueinander konvertieren.

Die Methode erase des std::vector<int> Containers kann nur mit Iteratoren zu Elementen desselben Vektors arbeiten. Wie bereits erwähnt wurde dies kann als Zeiger implementiert werden, aber es ist in der Regel nicht aus Gründen hier angegeben: C++ std::vector<>::iterator is not a pointer, why?

std::find Bedenken Sie:

template< class InputIt, class T > 
InputIt find(InputIt first, InputIt last, const T& value); 

Hier InputIt ein Template-Parameter ist. Die Vorlage std::find arbeitet mit jedem Iteratortyp, der die Anforderungen einer input iterator erfüllt und dessen operator* etwas zurückgibt, das mit dem Typ T verglichen werden kann. Zeiger funktionieren hier gut. Wie Fire Lancer in einem Kommentar richtig darauf hingewiesen hat, müssen sowohl first als auch last vom Typ InputIt sein.

Jetzt vergleichen Sie diese mit std::vector::erase:

iterator erase(const_iterator pos); 

Dies dauert eine const_iterator, die eine der typedefs der std::vector Klasse. Dies ist eine bestimmte Art von Iterator, kein Template-Parameter.

+1

Nun, ** Paare ** von Zeigern zu diesen Algorithmen zu übergeben ist effektiv ein Random-Access-Iterator-Typ. Aber Sie können immer noch einen Zeiger und einen Vektoriterator als ein "Paar" an diese übergeben, selbst wenn der Zeiger innerhalb des Vektors ist. –

1

Die Definition von vector.erase(...) ist

iterator erase(const_iterator pos);

Die const iterator eine Klasse für sich ist. Also, wenn es eine Konvertierung eines einfachen Zeigers zu dieser Klasse gab, dann könnte dies getan werden. Aber ich glaube nicht, dass es welche gibt.

Aber eine Sache ist, es an einer Stelle zu verwenden, wo ein Iterator erwartet wird, und eine andere ist, in Algorithmen zu verwenden.

Wenn ein iterator erforderlich ist, kann nur ein Iterator verwendet werden.

In Algorithmen wird eine iterator nicht erwartet. Nur ein Objekt, für das eine Concept einer iterator erfüllt ist (normalerweise eine begin und end geben den erforderlichen Iterator/Zeiger zurück).

+0

Algorithmen erwarten Iteratoren, nicht "Objekte, für die ein Anfang/Ende ...", was auch immer. – juanchopanza

+1

Algorithmen verwenden Vorlagen - die Parameter sind keine konkreten Arten von '' 'Iterator'''. Sie können jedes Objekt, das das Konzept eines "Iterators" erfüllt, an die Funktionen übergeben. –

+0

Mein Punkt genau. Danke für die Reparatur. – juanchopanza

0

Obwohl Zeiger Iteratoren sind, sind sie nicht die gleiche Typ als Vektor Iteratoren (zumindest sie müssen nicht sein).

Sie können einen Zeiger in ein Element eines Vektors in einen Itertor konvertieren, indem Sie Iterator- und Zeigerarithmetik wie folgt verwenden.

std::vector<int> v{1, 2, 3}; 

int* p = &v[0]; // a pointer 

auto v_iter = v.begin() + std::distance(v.data(), p); // an equivalent vector::iterator 

v.erase(v_iter); 

Dies funktioniert nur mit angrenzenden Containern wie std::vector oder std::array.