2009-05-03 11 views
5

Solo me pregunto, debido a un problema que me estoy encontrando, ¿es posible crear un vector de punteros? Y si es así, ¿cómo? Específicamente en relación con el uso de iteradores y .begin() con él, es decir: ¿Cómo me vuelvo este vector en un vector de punteros:¿Es posible crear un vector de punteros?

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

Respuesta

7

vector <c> cvect no es un vector de punteros. Es un vector de objetos de tipo c. Quiere vector <c*> cvect. y es probable que desee:

cvect.push_back(new c); 

Y entonces, dado un iterador, usted quiere algo como:

(*it)->func(); 

Por supuesto, es muy probable que no quería un vector de punteros en la primera place ...

+1

func() es una función virtual, así que supongo que se requiere el vector de punteros aquí. – Naveen

+0

ah sí - buen punto –

+1

Y si push_back() arroja, es probable que desee evitar la fuga de la nueva c. – bk1e

2

Usted ha creado vector<c*> como un vector de punteros. Luego use new para asignar la memoria para objetos c e insertarlos en el vector. Además, no olvide que tiene que marcar delete usted mismo y vector.clear() no liberará la memoria asignada para c objetos. Aquí debe almacenar c como un vector de punteros; de lo contrario, la llamada a la función virtual no funcionará.

2

Sí, claro.

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

Tenga en cuenta la declaración de vector<c*> cvect y el uso de cvect.push_back(&cobj).

Según el código proporcionado, está utilizando el iterador de forma incorrecta. Para acceder al miembro al que apunta un iterador, debe usar *citer en lugar de citer solo.

16

Sure.

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

cosas a tener en cuenta:

Tendrá que la limpieza después de su auto si se utiliza la memoria asignada dinámicamente como lo hice en mi ejemplo

por ejemplo:

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

Esto se puede simplificar usando un vector de shared_ptr s (como boost::shared_ptr). No intente utilizar std::auto_ptr para esto, no funcionará (ni siquiera compilará).

Otra cosa que debe tener en cuenta, debe evitar usar < para comparar iteradores en su ciclo cuando sea posible, solo funcionará para iteradores que modelen un iterador de acceso aleatorio, lo que significa que no puede cambiar su código para usar p.ej a std::list.

+0

+1, alcanzas todos los objetivos (que yo sepa, al menos ...) –

4

Sí, es posible, y de hecho es necesario utilizar punteros si pretende que su vector contenga objetos de una jerarquía de clases entera en lugar de un solo tipo. (Si no se utilizan los punteros, se generará el temido problema object slicing: todos los objetos se convierten silenciosamente al tipo de clase base. Esto no ha sido diagnosticado por el compilador y es casi seguro que no es lo que usted desea.)

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

Tenga en cuenta que con un vector de punteros, que tiene que hacer su propia gestión de memoria, así que mucho cuidado - si usted va a utilizar objetos locales (como el anterior), no deben caerse de alcance antes que el contenedor. Si utiliza punteros a objetos creados con new, necesitará delete manualmente antes de que se destruya el contenedor. Debería considerar utilizar punteros inteligentes en este caso, como el smart_ptr provisto por Boost.

0

Probar Boost Pointer Container Library. Tiene varias ventajas sobre el vector de punteros regular, como:

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 
Cuestiones relacionadas