70 votes

Renvoi d'un pointeur sur un élément vectoriel en c++.

J'ai un vecteur de myObjects dans la portée globale. J'ai une méthode qui utilise un std::vector<myObject>::const_iterator pour traverser le vecteur, et faire quelques comparaisons pour trouver un élément spécifique. Une fois que j'ai trouvé l'élément requis, je veux pouvoir renvoyer un pointeur vers celui-ci (le vecteur existe dans la portée globale).

Si je retourne &iterator Je renvoie l'adresse de l'itérateur ou l'adresse de ce vers quoi pointe l'itérateur ?

Est-ce que je dois lancer le const_iterator vers un myObject, puis renvoie l'adresse de ce myObject.

105voto

Renvoie l'adresse de la chose pointée par l'itérateur :

&(*iterator)

Edit : Pour dissiper toute confusion :

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
}

Pas besoin de vecteurs de pointeurs ou d'allocation dynamique.

15voto

Renvoyer &iterator retournera l'adresse de l'itérateur. Si vous voulez retourner un moyen de se référer à l'élément, retournez l'itérateur lui-même.

Attention, il n'est pas nécessaire que le vecteur soit un global pour retourner l'itérateur/pointeur, mais les opérations dans le vecteur peuvent invalider l'itérateur. L'ajout d'éléments au vecteur, par exemple, peut déplacer les éléments du vecteur à une position différente si la nouvelle taille() est supérieure à la mémoire réservée. La suppression d'un élément avant l'élément donné du vecteur fera en sorte que l'itérateur se réfère à un élément différent.

Dans les deux cas, en fonction de l'implémentation de la STL, il peut être difficile de déboguer avec des erreurs aléatoires qui se produisent très souvent.

EDIT après le commentaire : 'oui, je ne voulais pas retourner l'itérateur a) parce qu'il est constant, et b) parce qu'il n'est sûrement qu'un itérateur local et temporaire ? - Krakkos'

Les itérateurs ne sont pas plus ou moins locaux ou temporaires que n'importe quelle autre variable et ils sont copiables. Vous pouvez le retourner et le compilateur fera la copie pour vous comme il le fera avec le pointeur.

Maintenant avec la constance. Si l'appelant veut effectuer des modifications sur l'élément retourné (qu'il s'agisse d'un pointeur ou d'un itérateur), vous devez utiliser un itérateur non constant. (Il suffit de supprimer le "const_" de la définition de l'itérateur).

3voto

aJ. Points 17014

Ce n'est pas une bonne idée de renvoyer des itérateurs. Les itérateurs deviennent invalides lorsque des modifications sont apportées au vecteur (inversion \deletion ) se produit. De plus, l'itérateur est un objet local créé sur la pile et donc renvoyer l'adresse de celui-ci n'est pas du tout sûr. Je vous suggère de travailler avec myObject plutôt qu'avec des itérateurs vectoriels.

EDIT : Si l'objet est léger, il est préférable de renvoyer l'objet lui-même. Sinon, il faut retourner les pointeurs vers monObjet stocké dans le vecteur.

3voto

Aaron Saarela Points 2605

Tant que votre vecteur reste dans la portée globale, vous pouvez revenir :

&(*iterator)

Je vous préviens que c'est assez dangereux en général. Si votre vecteur est déplacé hors de la portée globale et est détruit, tous les pointeurs vers myObject deviennent invalides. Si vous écrivez ces fonctions dans le cadre d'un projet plus vaste, le fait de renvoyer un pointeur non-const peut amener quelqu'un à supprimer la valeur de retour. Cela aura des effets indéfinis, et catastrophiques, sur l'application.

Je réécrirais ça comme :

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

Si vous devez modifier le myObject retourné, stockez vos valeurs en tant que pointeurs et allouez-les sur le tas :

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

De cette façon, vous avez le contrôle sur le moment où ils sont détruits.

Quelque chose comme ça va casser votre application :

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

0voto

Naveen Points 37095

Vous stockez les copies de myObject dans le vecteur. Je pense donc que la copie de l'instance de monObjet n'est pas une opération coûteuse. Alors je pense que le plus sûr serait de retourner une copie de myObject depuis votre fonction.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X