2016-05-08 7 views
4

Ich würde gerne wissen, wenn es möglich ist, einen Iterator zu einem Objekt in einem Container (z. B. std::vector<...>) erhalten nur durch Zugriff auf das Objekt im Inneren des Containers, z. durch einen Verweis (was bedeutet, dass wir Zugriff auf einen Zeiger auf es mit dem &-Operator haben). Zum Beispiel, in der Regel erklären wir einen Iterator alsErhalten Iterator von Zeiger oder Referenz

std::vector<int>::iterator = vec.begin(); 

oder

std::vector<int>::iterator = next(vec.begin(), idx); 

aber im ersten Beispiel sind wir höchstwahrscheinlich etwa durch den Behälter, um zu durchlaufen, während im zweiten Beispiel, das wir kennen der Index des Objekts, das wir benötigen. Ich würde gerne wissen, ob wir den Iterator für ein Objekt erhalten können, ohne zu wissen, auf welchem ​​Index es sich im Container befindet, aber ob wir eine Referenz oder einen Zeiger darauf haben, wie oben erklärt.

Es könnte scheinen, dass diese Frage bereits here gestellt worden ist, aber es scheint mehr wie die OP wollte andere seinen Code zu beheben, anstatt die allgemeine Frage zu beantworten, so dass die Antworten meiner Meinung nach nicht so zufriedenstellend sind. Auch scheint die Antwort here zu sagen, dass wir einen Iterator mit einem Konstruktor initialisieren können, wie weiter unten

gezeigt
std::vector<int>::iterator it(...); 

aber ich habe nicht in der Lage gewesen, für die std :: Iterator-Klasse keine Beweise für einen Konstruktor zu finden in der offizielle Dokumentation (und ich konnte auch keine Dokumentation über std :: vector < ...> :: iterator finden), also bin ich vorsichtig, den oben gezeigten Konstruktor zu verwenden, auch wenn es kompiliert.

HINWEIS

Ich benutze std::vector als Beispiel oben, sondern im Idealfall würde ich dies für jeden Behälter zu arbeiten, zum Beispiel std::list oder std::deque

+1

Sie können einen Index durchlaufen. 'vec.begin() + (pos- & vec [0])' –

+0

@KonradKapp dann sollten Sie nach Fragen suchen, wie man den Index findet ;-) –

+0

@dyp ja, tut mir leid, dass ich das erste Mal nicht klar bin. Ich habe der Frage eine Notiz hinzugefügt. Ich bevorzuge den Iterator, da ich ihn als Unterbrechungsbedingung in einer for-Schleife verwenden möchte. Aber das ist nebensächlich :) Die Frage ist allgemeiner, ob man einen Iterator auf diese Weise erhalten könnte (scheint aber etwas zu sein, was einfach sein sollte) –

Antwort

9

Speziell für std::vector (und andere zusammenhängende Behälter wie std::string), einen Zeiger auf ein Objekt in dem p Vektor gegeben, können wir einfach tun:

auto iter = v.begin() + std::distance(v.data(), p); 

Dies wird durch den Kontiguität Vertrag garantiert. Beachten Sie, dass der Direktzugriff hier nicht ausreicht, das obige funktioniert nicht für std::deque.

Für jeden anderen Container gibt es keine einfache Möglichkeit, dies zu tun. Sie müßten nur find_if verwenden:

auto iter = std::find_if(c.begin(), c.end(), [p](auto const& o) { return &o == p; }); 

Für intrusive Container, wird der Iterator in das Objekt selbst irgendwie codiert werden, so wird es für die Umwandlung von p zu einem Iterator einig direkter Mechanismus sein. Aber das hängt vom intrusiven Container selbst ab.

+0

Beachten Sie jedoch, dass Sie selbst für zusammenhängende Datenstrukturen wissen müssen, welcher * Container das Objekt enthält. Der Versuch, einen Iterator mit einem Zeiger auf ein Objekt wiederherzustellen, das sich in einem anderen Container (oder gar keinem) befindet, schlägt fehl. –

+0

@ DietmarKühl um klar zu sein, wenn du sagst * welcher * container, du meinst eigentlich welchen * typ * container, (zB ob es "vektor", "liste" oder "deque" ist, zum beispiel) und nicht Welche * Instanz * eines Containers? (zum Beispiel zwischen Instanzen von "Vektor"?) –

+0

@KonradKapp Er bedeutet, welche Instanz. – Barry

1

Sie können die find Funktion --- es gibt einen Iterator ---, unterstützt auf (fast?) Alle Container, um Ihre Objekte zu finden. Wenn mehrere Objekte vorhanden sind, die unter operator== gleich sind, iterieren, bis das Objekt mit der gleichen Adresse gefunden wurde.

0

Seit C++ 11 können Sie das Schlüsselwort auto verwenden, um den Typ abzuleiten, es erleichtert das Schreiben des Typs.Wenn wir den Index kennen, können wir einen Iterator durch begin() + index bekommen.

Und wenn wir den Index nicht kennen, könnten wir die std::distance() von Anfang und den anderen Iterator verwenden, der uns einen Iterator für das gleiche Element geben wird.

// if we know the index 
auto it1 = begin(vec) + 4; 
cout << *it1; 

// if we don't know the index 
auto p = begin(vec) + 3; 
auto it2 = begin(vec) + distance(begin(vec), p+1); 
cout << *it2;