2009-05-03 6 views
5

Je me demande simplement, à cause d'un problème que je rencontre, est-il possible de créer un vecteur de pointeurs? Et si oui, comment? Plus précisément en ce qui concerne l'aide (itérateurs et .begin) avec elle, à savoir: Comment puis-je tourner ce vecteur dans un vecteur de pointeurs:Est-il possible de créer un vecteur de pointeurs?

class c 
{ 
    void virtual func(); 
}; 

class sc:public c 
{ 
    void func(){cout<<"using func";} 
}; 

sc cobj; 

vector<c>cvect 
cvect.push_back(cobj); 
vector<c>::iterator citer 

for(citer=cvect.begin();citer<cvect.end();citer++) 
{ 
    citer->func(); 
} 

Répondre

7

vector <c> cvect n'est pas un vecteur de pointeurs. C'est un vecteur d'objets de type c. Vous voulez vector <c*> cvect. et vous voulez probablement:

cvect.push_back(new c); 

Et puis, étant donné un itérateur, vous voulez quelque chose comme:

(*it)->func(); 

Bien sûr, il est tout à fait probable que vous ne vouliez pas un vecteur de pointeurs dans la première place ...

+1

func() est une fonction virtuelle, donc je suppose que vecteur de pointeurs est nécessaire ici. – Naveen

+0

ah oui - bon point –

+1

Et si push_back() jette, vous voulez probablement éviter de fuir le nouveau c. – bk1e

2

Vous avez créé vector<c*> pour un vecteur de pointeurs. Ensuite, utilisez new pour allouer la mémoire pour les objets c et les pousser dans le vecteur. De plus, n'oubliez pas que vous devez vous-même delete et vector.clear() ne libèrera pas la mémoire allouée pour les objets c. Vous devez stocker c comme un vecteur de pointeurs ici, sinon l'appel à la fonction virtuelle ne fonctionnera pas.

2

Oui, bien sûr.

// TestCPP.cpp : Defines the entry point for the console application. 
// 

#include "stdafx.h" 
#include <iostream> 
#include <vector> 


using namespace std; 

class c 
{ 
public: 
    void virtual func() = 0; 
}; 

class sc:public c 
{ 
public: 
    void func(){cout<<"using func";} 
}; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    sc cobj; 

    vector<c*> cvect; 
    cvect.push_back(&cobj); 
    vector<c*>::iterator citer; 

    for(citer=cvect.begin();citer<cvect.end();citer++) 
    { 
     (*citer)->func(); 
    } 

    return 0; 
} 

S'il vous plaît noter que la déclaration de vector<c*> cvect et l'utilisation de cvect.push_back(&cobj). À partir du code fourni, vous utilisez incorrectement l'itérateur. Pour accéder au membre un itérateur pointe vers vous devez utiliser *citer au lieu de citer seul.

16

Bien sûr.

vector<c*> cvect; 
cvect.push_back(new sc); 
vector<c*>::iterator citer; 
for(citer=cvect.begin(); citer != cvect.end(); citer++) { 
    (*citer)->func(); 
} 

choses à garder à l'esprit:

Vous aurez besoin de nettoyage après votre auto si vous utilisez la mémoire allouée dynamiquement comme je l'ai fait dans mon exemple

par exemple:

for(...) { delete *i; } 

Cela peut être simplifié en utilisant un vecteur de shared_ptr s (comme boost::shared_ptr). N'essayez pas d'utiliser std::auto_ptr pour cela, cela ne fonctionnera pas (ne compilera même pas). Autre chose à garder à l'esprit, évitez d'utiliser < pour comparer les itérateurs de votre boucle lorsque cela est possible, cela ne fonctionnera que pour les itérateurs qui modélisent un itérateur à accès aléatoire, ce qui signifie que vous ne pouvez pas changer votre code pour l'utiliser par exemple un std::list.

+0

+1, vous avez touché toutes les cibles (que je connais au moins ...) –

4

Oui, il est possible, et en fait il est nécessaire d'utiliser des pointeurs si vous souhaitez que votre vecteur contienne des objets d'une hiérarchie de classe entière plutôt que d'un seul type. (Ne pas utiliser les pointeurs entraînera le redouté problème de object slicing - tous les objets sont convertis silencieusement en type de classe de base.Cela n'est pas diagnostiqué par le compilateur, et n'est certainement pas ce que vous voulez.)

class c 
{ 
    void virtual func(); 
}; 

class sc:public c 
{ 
    void func(){cout<<"using func";} 
}; 

sc cobj; 

vector<c*> cvect;    // Note the type is "c*" 
cvect.push_back(&cobj);  // Note the "&" 
vector<c*>::iterator citer; 

for(citer=cvect.begin();citer != cvect.end();citer++) // Use "!=" not "<" 
{ 
    (*citer)->func(); 
} 

Notez que avec un vecteur de pointeurs, que vous devez faire votre propre gestion de la mémoire, soyez donc très prudent - si vous utilisez des objets locaux (comme ci-dessus), ils ne doivent pas tomber de portée avant le conteneur. Si vous utilisez des pointeurs vers des objets créés avec new, vous devrez les delete manuellement avant la destruction du conteneur. Vous devez absolument envisager d'utiliser des pointeurs intelligents dans ce cas, tels que le smart_ptr fourni par Boost.

0

Essayez Boost Pointer Container Library. Il a plusieurs avantages par rapport à vecteur régulier de pointeurs, comme:

my_container.push_back(0);   // throws bad_ptr 
ptr_vector<X> pvec; 
std::vector<X*> vec; 
(*vec.begin())->foo(); // call X::foo(), a bit clumsy 
pvec.begin()->foo();  // no indirection needed 
Questions connexes