Domanda

Ho un vettore di myObjects in ambito globale. Ho un metodo che utilizza un std :: vector < myObject > :: const_iterator per attraversare il vettore e fare alcuni confronti per trovare un elemento specifico. Una volta trovato l'elemento richiesto, voglio essere in grado di restituire un puntatore ad esso (il vettore esiste in ambito globale).

Se restituisco & amp; iteratore , sto restituendo l'indirizzo dell'iteratore o l'indirizzo di ciò a cui punta l'iteratore?

Devo ricollegare il const_iterator su un myObject, quindi restituire l'indirizzo di quello?

È stato utile?

Soluzione

Restituisce l'indirizzo della cosa indicata dall'iteratore:

&(*iterator)

Modifica: Per chiarire un po 'di confusione:

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
}

Non sono necessari vettori di puntatori o allocazione dinamica.

Altri suggerimenti

Il ritorno & amp; iteratore restituirà l'indirizzo dell'iteratore. Se si desidera restituire un modo di fare riferimento all'elemento, restituire lo stesso iteratore.

Attenzione che non è necessario che il vettore sia globale per restituire l'iteratore / puntatore, ma che le operazioni nel vettore possono invalidare l'iteratore. L'aggiunta di elementi al vettore, ad esempio, può spostare gli elementi vettoriali in una posizione diversa se la nuova dimensione () è maggiore della memoria riservata. La cancellazione di un elemento prima del dato elemento dal vettore farà fare in modo che l'iteratore faccia riferimento a un altro elemento.

In entrambi i casi, a seconda dell'implementazione STL, può essere difficile eseguire il debug con errori casuali che si verificano ciascuno di essi così spesso.

MODIFICA dopo commento: 'sì, non volevo restituire l'iteratore a) perché è const e eb) sicuramente è solo un iteratore locale temporaneo? - Krakkos '

Gli iteratori non sono più o meno locali o temporanei di qualsiasi altra variabile e sono copiabili. Puoi restituirlo e il compilatore farà la copia per te come farà con il puntatore.

Ora con la costanza. Se il chiamante desidera eseguire modifiche tramite l'elemento restituito (puntatore o iteratore), è necessario utilizzare un iteratore non const. (Rimuovi semplicemente 'const_' dalla definizione dell'iteratore).

Non è una buona idea restituire iteratori. Gli iteratori diventano non validi quando si verificano modifiche al vettore (inversione / cancellazione). Inoltre, l'iteratore è un oggetto locale creato in pila e quindi restituire l'indirizzo dello stesso non è affatto sicuro. Ti consiglierei di lavorare con myObject piuttosto che con gli iteratori vettoriali.

Modifica Se l'oggetto è leggero, è meglio restituire l'oggetto stesso. In caso contrario, restituisce i puntatori a myObject archiviati nel vettore.

Finché il tuo vettore rimane nell'ambito globale puoi tornare:

&(*iterator)

Ti avvertirò che questo è abbastanza pericoloso in generale. Se il tuo vettore viene mai spostato dall'ambito globale e viene distrutto, tutti i puntatori a myObject diventano non validi. Se stai scrivendo queste funzioni come parte di un progetto più grande, la restituzione di un puntatore non const potrebbe indurre qualcuno a eliminare il valore restituito. Ciò avrà effetti indefiniti e catastrofici sull'applicazione.

Lo riscrivo come:

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

Se è necessario modificare myObject restituito, archiviare i valori come puntatori e allocarli nell'heap:

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

In questo modo hai il controllo su quando vengono distrutti.

Qualcosa del genere romperà la tua app:

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());

Puoi utilizzare la funzione dati del vettore:

  

Restituisce un puntatore al primo elemento nel vettore.

Se non vuoi il puntatore al primo elemento, ma per indice, puoi provare, ad esempio:

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

Supponiamo che tu abbia:

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

Quindi il primo oggetto nel vettore è: * first . Per ottenere l'indirizzo, utilizzare: & amp; (* first) .

Tuttavia, in linea con il design STL, suggerirei invece di restituire un iteratore se prevedi di passarlo in seguito agli algoritmi STL.

Stai memorizzando le copie di myObject nel vettore. Quindi credo che copiare l'istanza di myObject non sia un'operazione costosa. Quindi penso che il più sicuro sarebbe restituire una copia di myObject dalla tua funzione.

Fai riferimento alle risposte di dirkgently e anon, puoi chiamare la funzione fronte invece di inizia , quindi non devi scrivere il * , ma solo & amp; .

Esempio di codice:

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.

Non sono sicuro se sia necessario restituire l'indirizzo della cosa indicata dall'iteratore. Tutto ciò che serve è il puntatore stesso. Vedrai la stessa classe iteratrice di STL implementare l'uso di _Ptr per questo scopo. Quindi, basta fare:

return iterator._Ptr;
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top