2012-01-25 15 views
5

cómo puedo acceder a los elementos de myVector como yo haría con matrices (for(i = 0; i < n; i++) cout << v[i] << " ";)C++ Accediendo a los elementos vectoriales

Mi código:

#include <iostream> 
#include <vector> 
#include <string> 
using namespace std; 

class Month 
{ 
public: 
    char *name; 
    int nr_days; 
    Month(char* c, int nr) : name(c), nr_days(nr){}; 
    ~Month() { /* free(name); */} 
}; 

int main() 
{ 
    Month January("January", 31); 
    Month February("February", 28); 
    Month March("March", 31); 
    Month April("April", 30); 
    Month May("May", 31); 
    Month June("June", 30); 
    Month July("July", 31); 
    Month August("August", 31); 
    Month September("September", 30); 
    Month Octomber("Octomber", 31); 
    Month November("November", 30); 
    Month December("December", 31); 

    vector<Month> *myVect = new vector<Month>; 
    myVect->push_back(January); 
    myVect->push_back(February); 
    myVect->push_back(March); 
    myVect->push_back(April); 
    myVect->push_back(May); 
    myVect->push_back(June); 
    myVect->push_back(July); 
    myVect->push_back(August); 
    myVect->push_back(September); 
    myVect->push_back(Octomber); 
    myVect->push_back(November); 
    myVect->push_back(December); 

    for(vector<Month>::const_iterator i = myVect->begin(); i != myVect->end(); i++) 
    { 
     /* 
     Month myMonth = i; 
     cout << myMonth.name << " " << myMonth.nr_days << endl; 
     */ 
    } 

    free(myVect); 
    return 0; 
} 

me gustaría ser algo así como un algoritmo foreach: foreach(Month in myVect) cout << ...

Y otra pregunta: ¿por qué me da un error en tiempo de ejecución en el destructor si elimino el comentario de mi línea?

+0

En primer lugar, es probable que no desee hacer 'myVect' a * puntero *, pero si lo hace, debe asignar con nuevo. Me sorprende que no se cuelgue antes. – crashmstr

+0

Estoy pensando que el 'nuevo ...' fue eliminado en un Editar por Adam ...? – crashmstr

+0

@crashmstr: Lo fue. Por vergüenza, Adam, por vergüenza ... –

Respuesta

7

Ok, hay un montón de problemas aquí.

  1. Declara myVect como un puntero a un vector. Esto es innecesario. Uno de los principales beneficios de usar un vector es que no tiene que preocuparse por la administración de la memoria, ya que el vector lo hace por usted. Apila asignar el vector, pero internamente, el montón asigna la memoria utilizada para almacenar los elementos que contiene.

  2. Nunca inicializa el puntero. Estás invocando un comportamiento indefinido ya que ese puntero no es válido. Para inicializar un puntero, usa new. Todo lo que tiene es un puntero asignado de pila no válido que no apunta a un vector en el montón. EDITAR: Me acabo de dar cuenta de que el new fue editado, por lo que puede ignorar este. Aún así, no debería ser un puntero en absoluto.

  3. Está utilizando free para desasignar una clase de C++ (que nunca asignó para comenzar ...). No lo hagas Esto no es C, usa new y delete para administrar la memoria (¡cuando sea necesario!) En C++. free no llama destructores, simplemente libera un pedazo de memoria. delete por otro lado, ya que sabe cómo tratar con tipos complejos de C++. Nunca mix new/delete con malloc/free.

  4. myVect->begin() devuelve un const_iterator, no un T (es decir,, en este caso, no es un objeto Month). Dereferencing el repetidor a través del operador * producirá el objeto iteración actual, por lo que:


Month myMonth = *i // <--- IMPORTANT! 

Como acotación al margen, si va a ser un bucle sobre el vector a menudo es posible que desee a typedef el iterador para reducir el nivel de detalle, es decir,

typedef vector<Month>::const_iterator cmonth_iter; 

Ahora se puede escribir

for(cmonth_iter i = myVect.Begin(); i != myVect.end(); ++i) 
{ 
    Month m = *i; 
    // do stuff with m  
} 
2

Se puede acceder a los elementos que utilizan iterador utilizando el operador *:

for(vector<Month>::const_iterator i = myVect->begin(); i != myVect->end(); i++) 
{ 
    Month myMonth = *i; 
    cout << myMonth.name << " " << myMonth.nr_days << endl; 
} 

Además, nunca se asigna un vector en el código. No debe usar free() en un puntero que no haya recibido del malloc() anteriormente. Es un comportamiento indefinido hacer lo contrario y es probable que se produzca un error de tiempo de ejecución en el momento en que llame al free().

Prueba esto:

vector<Month> *myVect = new vector<Month>; 
... 
delete myVect; 
1

Si elimina el error de puntero no inicializado cambiando:

vector<Month> *myVect; 

a:

vector<Month> myVect; 

entonces esto va a funcionar. (Una vez que defina ostream << Month)

for(i = 0; i < myVect.size(); i++) 
cout << v[i] << " "; 
0
  1. Usted tiene un puntero myVect, pero nunca asignar un valor a la misma antes de usar (advertencias del compilador activar). deberías hacer algo como myVect = new vector<Month>(). (o no lo haga puntero y cambie -> en .). El resto de su implementación "foreach" se ve bien. Y puede usar [] para acceder a los elementos también.

  2. Libera cadenas constantes, no las asignó, por lo que no necesita liberarlas tampoco.

0

Estás declarando myVect como un puntero, pero nunca su asignación, que va a darle un montón de problemas. Solo suelta el * y deberías estar bien.

Si insisten, se puede utilizar un índice igual que lo haría con una matriz:

for(int i = 0; i < myVect.size(); i++) 
{   
    Month myMonth = myVect[i]; 
    cout << myMonth.name << " " << myMonth.nr_days << endl; 
} 

Aunque yo prefiero usar iteradores como lo han hecho - sólo una solución sencilla:

Month myMonth = *i; 
0

se puede utilizar el operador de flecha con iteradores ...

for(vector<Month>::const_iterator i = myVect->begin(); i != myVect->end(); i++) 
{ 
    cout << i->name << " " << i->nr_days << endl; 
} 

nota también de que es más idiomática con iteradores que usan ++i en lugar de i++ (la razón es que i++ necesitarán crear una copia del iterador que se descartará).

Tenga en cuenta también que su código es UB (comportamiento indefinido) porque está utilizando un puntero a un vector, pero no lo está asignando. Por cierto, el uso de un puntero en este caso no tiene sentido, el código sería correcto y sencillo con:

vector<Month> myVect; 
myVect.push_back(January); 
myVect.push_back(February); 
... 
for(vector<Month>::const_iterator i = myVect.begin(); i != myVect->end(); ++i) 
    ... 

Mi sugerencia es también evitar intentar aprender C++ simplemente mediante la experimentación con un compilador (algo que yo tengo la impresión de que estás tratando de hacer).

C++ es potente pero también complejo y lamentablemente bastante ilógico y asimétrico en muchas partes (debido a su historial de evolución). Agregue a esto que cuando comete un error (por ejemplo, no asignar el vector en su código original) no puede esperar que el compilador lo ayude e incluso en el tiempo de ejecución el programa puede hacer CUALQUIER COSA, incluyendo aparentemente trabajar como esperaba (lo peor posible) . Este combo es mortal.

La complejidad, la asimetría y la falta de controles en el tiempo de ejecución hacen que C++ sea imposible de aprender mediante la experimentación ... solo obtenga good book y léalo. Es mucho más simple de esta manera.

Cuestiones relacionadas