2013-02-18 2 views
0

Comment obtenir la position d'un élément dans un vecteur, où les éléments sont des classes. Y-a-t'il une façon de le faire?Get Element Position dans std :: vector

code Exemple:

class Object 
{ 
    public: 
    void Destroy() 
    { 
     // run some code to get remove self from vector 
    } 
} 

En main.cpp:

std::vector<Object> objects; 
objects.push_back(<some instances of Object>); 
// Some more code pushing back some more stuff 

int n = 20; 
objects.at(n).Destroy(); // Assuming I pushed back 20 items or more 

Je suppose que je veux être en mesure d'écrire une méthode ou quelque chose qui est un membre de la classe qui sera de retour l'emplacement de lui-même à l'intérieur du vecteur ... Est-ce possible?

EDIT:

En raison de la confusion, je dois expliquer mieux. Le problème est, comment puis-je trouver le numéro pour faire l'effacement ...? Apparemment, ce n'est pas possible ... Je pensais que ce ne serait peut-être pas ...

+0

Écrivez un opérateur de comparaison approprié pour votre classe qui reflète la sémantique dont vous avez besoin, puis utilisez 'std :: find'. – us2012

+2

Pourquoi l'objet se soucie-t-il s'il fait partie d'un vecteur, d'une liste ou d'une deque? –

+0

J'ai peur de ne pas comprendre ce que vous venez de dire. J'ai besoin d'écrire un 'operator == (...)' et d'utiliser std :: find qui est un code qui fait quoi? – user3728501

Répondre

0

Les objets dans un vecteur ne savent pas automatiquement où ils se trouvent dans le vecteur.

Vous pouvez fournir chaque objet avec cette information, mais beaucoup plus facile: retirez l'objet du vecteur. Son destructeur est ensuite exécuté automatiquement.

Ensuite, les objets peuvent également être utilisés dans d'autres conteneurs.


Exemple:.

#include <algorithm> 
#include <iostream> 
#include <vector> 

class object_t 
{ 
private: 
    int  id_; 
public: 
    int id() const { return id_; } 

    ~object_t() {} 
    explicit object_t(int const id): id_(id) {} 
}; 

int main() 
{ 
    using namespace std; 
    vector<object_t> objects; 

    for(int i = 0; i <= 33; ++i) 
    { 
     objects.emplace_back(i); 
    } 

    int const n = 20; 
    objects.erase(objects.begin() + n); 

    for(auto const& o : objects) 
    { 
     cout << o.id() << ' '; 
    } 
    cout << endl; 
} 
+0

Oui, j'ai l'impression que vous n'avez pas compris la question. Destroy est une méthode qui fera l'enlèvement. – user3728501

+0

Ok, une modification a été faite, merci, je vais regarder dans la mise en œuvre de ce. – user3728501

1

Vous pouvez utiliser std::find pour trouver des éléments dans vector (vous fournir à mettre en œuvre un opérateur de comparaison (==) pour Object Cependant, 2 grandes préoccupations:

  1. Si vous avez besoin de trouver des éléments dans un conteneur, vous obtiendrez de meilleures performances en utilisant un conteneur ordonné tel que std::map ou std::set (trouver opérations dans O(log(N)) vs O(N)
  2. Object ne devrait pas être le seul responsable de se retirer du conteneur. Object ne devrait pas savoir ou se préoccuper de l'endroit où il se trouve, car cela casse l'encapsulation. Au lieu de cela, le propriétaire du conteneur devrait s'occuper de ces tâches.
+0

Malheureusement, il serait préférable que nous ignorions les règles d'encapsulation. – user3728501

+0

Parfois? sûr. En règle générale? Définitivement pas. Les objets ne doivent généralement PAS être "conscients" du contexte dans lequel ils seront stockés. Ils peuvent limiter ce contexte via Singletons, les constructeurs privés, etc. mais sachant explicitement que le type de votre propriétaire n'est jamais positif (peut-être une interface). , mais même cela devrait être évité si possible) – eladidan

+0

Ouais c'est un de ces cas, mais je n'écris pas une interface. – user3728501

0

Si vous avez besoin de détruire l'élément de n'th dans un vecteur alors la meilleure façon est d'obtenir un itérateur depuis le début en utilisant std::begin() et appeler std::advance() pour faire avancer la façon dont jamais de places que vous voulez, donc quelque chose comme:

std::vector<Object> objects; 
const size_t n = 20; 

auto erase_iter = std::advance(std::begin(objects), n); 

objects.erase(erase_iter); 

Si vous voulez trouver l'index d'un élément dans un vecteur puis utilisez std::find pour obtenir le iterator et appeler std::distance depuis le début.

donc quelque chose comme:

Object object_to_find; 
std::vector<Object> objects; 

auto object_iter = std::find(std::begin(objects), std::end(objects), object_to_find); 

const size_t n = std::distance(std::begin(objects), object_iter); 

Cela ne signifie pas que vous devez mettre en œuvre un opérateur d'égalité pour votre objet.Ou vous pouvez essayer quelque chose comme:

auto object_iter = std::find(std::begin(objects), std::end(objects), 
    [&object_to_find](const Object& object) -> bool { return &object_to_find == &object; }); 

Bien que cela fonctionne le object_to_find doit être celle de la liste réelle telle qu'elle est simplement comparer les adresses.

+0

Le problème est de trouver quelles seront les valeurs de n. – user3728501

1

L'objet peut s'effacer ainsi:

void Destroy(std::vector<Object>& container); 
{ 
    container.erase(container.begin() + (this - &container[0])); 
} 

Cela fonctionne comme prévu, mais il me semble que la conception exceptionnellement mauvaise. Les membres ne devraient pas avoir connaissance de leurs conteneurs. Ils devraient exister (de leur propre point de vue) dans un vide non identifiable. La création et la destruction devraient être laissées à leur créateur.

+0

Oui, je pense que c'est exactement ce que je veux. – user3728501

+0

Sachez que l'objet n'existe plus après l'appel de '.erase()'. Ainsi, par exemple, vous ne devez pas référencer de variables membres ou appeler des fonctions membres. Pour être sûr, la seule chose que vous devriez faire après '.erase()' est 'return;'. –

+0

En outre, cette solution est spécifique à 'std :: vector <>' en raison de l'arithmétique du pointeur. Les autres conteneurs n'ont pas d'objets contigus. Cela ne fonctionnera pas sur 'std :: list <>', 'std :: set <>', etc., et peut ne pas fonctionner sur 'std :: vector '. –