2009-03-13 7 views
51

Ich habe einen Vektor von MyObjects im globalen Bereich. Ich habe eine Methode, die eine std::vector<myObject>::const_iterator verwendet, um den Vektor zu durchlaufen und einige Vergleiche zu tun, um ein bestimmtes Element zu finden. Sobald ich das erforderliche Element gefunden habe, möchte ich einen Zeiger darauf zurückgeben können (der Vektor existiert im globalen Bereich).Zurückgeben eines Zeigers auf ein Vektorelement in C++

Wenn ich &iterator zurückgebe, gebe ich die Adresse des Iterators oder die Adresse zurück, auf die der Iterator zeigt?

Habe ich die const_iterator zurück zu einem myObject werfen müssen, dann wieder die Adresse, dass ??

+0

Ich schlage vor, Sie diesen Artikel von Scott Meyers lesen über Iteratoren Nutzung: http://www.ddj.com/cpp/184401406 gibt er Richtlinien über const_iterator Umwandlung iterator usw. –

Antwort

74

Rückkehr die Adresse der Sache durch den Iterator zeigte:

&(*iterator) 

Edit: Um einige Verwirrung aufklären:

vector <int> vec;   // a global vector of ints 

void f() { 
    vec.push_back(1); // add to the global vector 
    vector <int>::iterator it = vec.begin(); 
    * it = 2;    // change what was 1 to 2 
    int * p = &(*it);  // get pointer to first element 
    * p = 3;    // change what was 2 to 3 
} 

Keine Notwendigkeit für Vektoren von Zeigern oder dynamische Zuordnung.

+60

Ich glaube nicht, dass es eine gute Idee ist, den Zeiger auf das im Vektor gespeicherte Objekt zurückzugeben. Was passiert, wenn Vektor jemand eine push_back() macht, nachdem wir den Zeiger erhalten haben. Der Vektor kann die Größe ändern und der Zeiger kann ungültig werden, oder? – Naveen

+1

Genau dasselbe gilt für Iteratoren. –

+3

Ja, deshalb glaube ich, dass der sicherste Weg die Kopie ist. – Naveen

3

Es ist keine gute Idee, Iteratoren zurückzugeben. Iteratoren werden ungültig, wenn Änderungen am Vektor (Inversion \ Deletion) auftreten. Außerdem ist der Iterator ein lokales Objekt, das auf dem Stapel erstellt wird, und daher ist die Rückgabe der Adresse desselben nicht sicher. Ich würde vorschlagen, dass Sie mit myObject statt mit Vektor-Iteratoren arbeiten.

EDIT: Wenn das Objekt leicht ist, dann ist es besser, Sie das Objekt selbst zurückgeben. Otherwise gibt Zeiger auf myObject zurück, die im Vektor gespeichert sind.

0

Sag mal, haben Sie die folgenden Schritte aus:

std::vector<myObject>::const_iterator first = vObj.begin(); 

Dann wird das erste Objekt im Vektor ist: *first. Um die Adresse zu erhalten, verwenden Sie: &(*first).

In Übereinstimmung mit dem STL-Design würde ich jedoch vorschlagen, einen Iterator zurückzugeben, wenn Sie ihn später an STL-Algorithmen weitergeben möchten.

+0

Ich möchte einen Zeiger auf ein myObject im Vektor zurückgeben ... die Implementierung, wie dieser Zeiger meine Änderung gefunden wird, daher wollte ich keinen Iterator zurückgeben. – Krakkos

12

Rückgabe & Iterator gibt die Adresse des Iterators zurück. Wenn Sie einen Verweis auf das Element zurückgeben möchten, geben Sie den Iterator selbst zurück.

Beachten Sie, dass Sie den Vektor nicht als global verwenden müssen, um den Iterator/Zeiger zurückzugeben, sondern dass Operationen im Vektor den Iterator ungültig machen können. Das Hinzufügen von Elementen zum Vektor kann z. B. die Vektorelemente an eine andere Position verschieben, wenn die neue Größe() größer als der reservierte Speicher ist. Das Löschen eines Elements vor dem gegebenen Element aus dem Vektor bewirkt, dass der Iterator auf ein anderes Element verweist.

In beiden Fällen kann es je nach STL-Implementierung schwierig sein, mit nur gelegentlich auftretenden Fehlern zu debuggen.

BEARBEITEN nach Kommentar: 'ja, ich wollte den Iterator nicht zurückgeben a) weil sein const, und b) sicher ist es nur ein lokaler, temporärer Iterator?- Krakkos '

Iteratoren sind nicht mehr oder weniger lokal oder temporär als jede andere Variable und sie sind kopierbar. Sie können es zurückgeben und der Compiler wird die Kopie für Sie machen, so wie es mit dem Zeiger wird.

Jetzt mit der Const-Ness. Wenn der Aufrufer Änderungen über das zurückgegebene Element (ob Zeiger oder Iterator) durchführen möchte, sollten Sie einen nichtkonstanten Iterator verwenden. (Entfernen Sie einfach 'const_' aus der Definition des Iterators).

+0

Ja, ich wollte den Iterator nicht ausgeben a) weil sein const, und b) sicher ist es nur ein lokaler, temporärer Iterator? – Krakkos

0

Sie speichern die Kopien des myObject im Vektor. Ich glaube also, dass das Kopieren der Instanz von myObject keine kostspielige Operation ist. Dann denke ich, dass das sicherste eine Kopie des myObject von deiner Funktion zurückgeben würde.

+0

Ich muss einige der Eigenschaften des zurückgegebenen myObject ändern, also wollte ich keine Kopie erstellen ... Mit der Zeigermethode kann ich sie direkt bearbeiten. – Krakkos

3

Solange Ihr Vektor im globalen Rahmen bleibt, kann man zurück:

&(*iterator) 

ich Sie warnen, werden feststellen, dass dies in der Regel ziemlich gefährlich ist. Wenn Ihr Vektor jemals aus dem globalen Gültigkeitsbereich entfernt wird und zerstört wird, werden alle Zeiger auf myObject ungültig. Wenn Sie diese Funktionen als Teil eines größeren Projekts schreiben, kann die Rückgabe eines nicht konstanten Zeigers dazu führen, dass der Rückgabewert gelöscht wird. Dies hat undefinierte und katastrophale Auswirkungen auf die Anwendung.

Ich würde umschreiben dies als:

myObject myFunction(const vector<myObject>& objects) 
{ 
    // find the object in question and return a copy 
    return *iterator; 
} 

Wenn Sie das zurück myObject ändern müssen, speichern Sie Ihre Werte als Zeiger und verteilen sie auf dem Heap:

myObject* myFunction(const vector<myObject*>& objects) 
{ 
    return *iterator; 
} 

Auf diese Weise haben Sie Kontrolle darüber, wann sie zerstört werden.

So etwas wird Ihre App brechen:

g_vector<tmpClass> myVector; 

    tmpClass t; 
    t.i = 30; 
    myVector.push_back(t); 

    // my function returns a pointer to a value in myVector 
    std::auto_ptr<tmpClass> t2(myFunction()); 
+0

Die Verwendung von auto_ptr in einem Zeiger auf ein Objekt in einem globalen gespeichert ist wie Schießen Sie sich in den Fuß. Ich stimme zu, dass es gefährlich ist, einen Zeiger auf ein Objekt zurückzusetzen, dessen Lebensdauer sich ändern kann, aber auch Ihre Probe ist nicht realistisch. – Ismael

1

Sie können die Daten Funktion des Vektors verwenden:

Gibt einen Zeiger auf das erste Element in dem Vektor.

Wenn nicht die Zeiger auf das erste Element wollen, aber durch den Index, versuchen Sie können dann zum Beispiel:

//the index to the element that you want to receive its pointer: 
int i = n; //(n is whatever integer you want) 

std::vector<myObject> vec; 
myObject* ptr_to_first = vec.data(); 

//or 

std::vector<myObject>* vec; 
myObject* ptr_to_first = vec->data(); 

//then 

myObject element = ptr_to_first[i]; //element at index i 
myObject* ptr_to_element = &element; 
0

zu dirkgently der Siehe und Antworten des Anon, können Sie die Front rufen Funktion statt beginnen Funktion, so dass Sie nicht müssen die * schreiben, aber nur die &.

Codebeispiel:

vector<myObject> vec; //You have a vector of your objects 
myObject first = vec.front(); //returns reference, not iterator, to the first object in the vector so you had only to write the data type in the generic of your vector, i.e. myObject, and not all the iterator stuff and the vector again and :: of course 
myObject* pointer_to_first_object = &first; //* between & and first is not there anymore, first is already the first object, not iterator to it. 
0

Ich bin mir nicht sicher, ob die Adresse des von dem Iterator zeigt, was Rückkehr benötigt wird. Alles, was Sie brauchen, ist der Zeiger selbst. Sie werden sehen, dass die Iterator-Klasse von STL selbst die Verwendung von _Ptr für diesen Zweck implementiert.Also, nur:

return iterator._Ptr; 
Verwandte Themen