wake-up-neo.net

Rückgabe eines Zeigers auf ein Vektorelement in c ++

Ich habe einen Vektor von myObjects im globalen Gültigkeitsbereich . Ich habe eine Methode, die den Vektor mit einem std::vector<myObject>::const_iterator durchquert und einige Vergleiche durchführt, 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 Gültigkeitsbereich).

Wenn ich &iterator zurückschicke, erhalte ich die Adresse des Iterators oder die Adresse, auf die der Iterator verweist?

Muss ich den const_iterator wieder in ein myObject umwandeln und dann die Adresse dieses zurückgeben?

57
Krakkos

Gib die Adresse der Sache zurück, auf die der Iterator zeigt:

&(*iterator)

Bearbeiten: Um einige Verwirrungen zu beseitigen:

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 Vektoren von Zeigern oder dynamische Zuordnung erforderlich.

81
anon

Rückkehr & 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 der Vektor nicht global sein muss, um den Iterator/Zeiger zurückzugeben. Die Vorgänge im Vektor können den Iterator jedoch ungültig machen. Wenn Sie dem Vektor beispielsweise Elemente hinzufügen, können die Vektorelemente an eine andere Position verschoben werden, wenn die neue Größe () größer ist als der reservierte Speicher. Durch das Löschen eines Elements vor dem angegebenen Element aus dem Vektor wird der Iterator auf ein anderes Element verweisen.

In beiden Fällen kann es je nach STL-Implementierung schwierig sein, zu debuggen, wobei nur zufällige Fehler auftreten, die jeweils so oft auftreten.

BEARBEITEN Sie nach dem Kommentar: 'Ja, ich wollte den Iterator nicht zurückgeben a) weil er const ist, und b) es sich sicher nur um einen lokalen temporären Iterator handelt? - Krakkos '

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

Nun mit der Konstanz. Wenn der Aufrufer Änderungen durch das zurückgegebene Element (Zeiger oder Iterator) durchführen möchte, sollten Sie einen Nicht-Konstanten-Iterator verwenden. (Entfernen Sie einfach das 'const_' aus der Definition des Iterators).

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

EDIT: Wenn das Objekt leichtgewichtig ist, ist es besser, das Objekt selbst zurückzugeben. Andernfalls kehren Sie zu myObject zurück, die im Vektor gespeichert sind.

3
aJ.

Solange Ihr Vektor im globalen Bereich bleibt, können Sie Folgendes zurückgeben:

&(*iterator)

Ich warne Sie, dass dies im Allgemeinen ziemlich gefährlich ist. Wenn Ihr Vektor immer aus dem globalen Bereich verschoben 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 das wie folgt umschreiben:

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

Wenn Sie das zurückgegebene myObject ändern müssen, speichern Sie Ihre Werte als Zeiger und ordnen Sie sie dem Heap zu:

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

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

So etwas wird Ihre App zerstören:

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());
3
Aaron Saarela

Sie können die data - Funktion des Vektors verwenden:

Gibt einen Zeiger auf das erste Element im Vektor zurück.

Wenn der Zeiger nicht auf das erste Element, sondern auf den Index zugreifen soll, können Sie beispielsweise Folgendes versuchen:

//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;

Sie speichern die Kopien des myObject im Vektor. Ich glaube also, dass das Kopieren der Instanz von myObject kein kostspieliger Vorgang ist. Dann denke ich, dass es am sichersten wäre, eine Kopie des myObject von Ihrer Funktion zurückzugeben.

0
Naveen

Sagen Sie, Sie haben folgendes:

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

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

Im Einklang mit dem STL-Design würde ich jedoch empfehlen, stattdessen einen Iterator zurückzugeben, wenn Sie ihn später an STL-Algorithmen weitergeben möchten.

0
dirkgently

Beziehen Sie sich auf die Antworten von dirkgently und anon. Sie können statt der Funktion begin die Funktion front aufrufen. Daher müssen Sie not nicht den * schreiben, sondern nur den &.

Code-Beispiel:

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.

Ich bin nicht sicher, ob die Adresse des Dings, auf das der Iterator verweist, zurückgegeben werden soll. Alles, was Sie brauchen, ist der Zeiger selbst. Sie sehen, dass die Iterator-Klasse von STL selbst die Verwendung von _Ptr für diesen Zweck implementiert. Also mach einfach:

return iterator._Ptr;
0
arviman