¿Reservando y borrando vectores?

Tengo problemas para eliminar datos de un vector.

Cuando creo los datos, primero reservo espacio en una matriz, y luego cambio el tamaño del vector y copio las direcciones de la matriz:

//Create the vertices
verts.reserve(vn); verts.resize(vn);
TriVertex *vertsaux = new TriVertex[vn];

for(int i=0, c=0; i<vn; i++, c+=3)
{
     vertsaux[i].SetId(i);
     vertsaux[i].SetCoords0(Vector3(vs[c], vs[c+1], vs[c+2]));

     //Inicializate texture vertices
     vertsaux[i].SetTextureCoords(Vector2(0.0f, 0.0f));
}

for(int i=0; i<vn; i++)
{
     verts[i] = &vertsaux[i];
}

Pero en el destructor de mi clase, me da un error de tiempo de ejecución cuando hago esto:

for (i=0; i < this->verts.size(); i++) {
     delete this->verts[i];
}

¿Alguien sabe por qué puede estar pasando esto?

Por cierto, no puedo simplemente crear new TriVertex dentro de for, debido a algunos detalles de implementación ...

preguntado el 16 de mayo de 11 a las 18:05

¿Cómo es tu declaración de verts? Es vector o vector ? -

verts.reserve(vn); verts.resize(vn); es redundante. Todas las operaciones de vector que hacen crecer el vector harán la reserva por usted. Tu usas .reserve(N) solo cuando crezca el vector de forma incremental, conozca un tamaño final mínimo y no desee las reservas intermedias. -

No necesitas usar this-> para referirse a miembros de su propia clase. -

6 Respuestas

Asignas una matriz de objetos con

TriVertex *vertsaux = new TriVertex[vn];

Para borrar eso de nuevo necesitas hacer

delete[] vertsaux;

No puede eliminar los elementos individualmente.

contestado el 16 de mayo de 11 a las 22:05

Realmente no nos estás dando suficiente información. Cual es el tipo de verts? Y porque estas usando versaux? Por lo poco que puedo ver, la solución más lógica sería tener std::vector <TriVertex> verts; como miembro de la clase e inicializarlo directamente, sin las asignaciones dinámicas intermedias. Quizás:

verts.reserve(vn);

for ( int i = 0; i < vn; ++ i ) {
    verts.push_back( TriVertex() );
    TriVertex& current = verts.back();
    current.SetId( i );
    current.SetCoords( Vector3( *vs, *(vs+1), *(vs+ 2) ) );

    current.SetTextureCoords( Vector2( 0.0, 0.0 ) );
    vs += 3;
}

No veo ninguna razón para la matriz intermedia asignada dinámicamente. (Si lo hay, la respuesta de Joe es correcta).

contestado el 16 de mayo de 11 a las 22:05

In C++11 puedes usar std::vector::emplace_back(), que crea directamente el objeto en el vector. Esto erosiona aún más la necesidad de una gestión manual de la memoria. - tillaert

@tillaert No veo dónde cambia mucho con respecto a la necesidad de administración manual de memoria. De hecho, en este caso particular, sospecho que los constructores de movimientos y otras optimizaciones legales significan que emplace_back no hará mucha diferencia. (En otros casos, claro ...) - James Kanze

No quise decir eso con respecto a tu ejemplo, tu código está bien. Algunos programadores son muy exigentes con las optimizaciones y tienden a usar vectores de punteros para lograr este objetivo. Quería señalar que emplace y la semántica de movimientos erosiona este caso. Lamento si mi comentario causó confusión. - tillaert

Cuando asigna una matriz usando

TriVertex *vertsaux = new TriVertex[vn];

tienes que desasignar usando delete[] al

delete[] vertsaux;

contestado el 16 de mayo de 11 a las 22:05

Dado que crea una matriz de TriVertex, señalado por vertsaux, entonces debes eliminar la matriz usando:

delete[] vertsaux;

No puede eliminar los elementos individuales de la matriz.

Habiendo hecho lo anterior delete[], debes eliminar todos los elementos de verts Me gusta esto:

verts.clear();

Esto se debe a que, dado que ha eliminado vertsaux, los punteros en el interior verts no son válidos.

Supongo que verts es algo como: std::vector<TriVertex*>

contestado el 16 de mayo de 11 a las 22:05

Está bien. Entonces, ¿es correcto si hago esto ?: delete [] verts [0]; ¿O hay memoria que no se está borrando? - Sara

@Sara: No creo que tu debemos Hacer el delete[] verts[0], solo por el bien de la coherencia. - quamrana

delete this->verts[i];

Esto elimina un elemento dentro de la matriz asignada dinámicamente que creó y, en realidad, es UB eliminarlo de esa manera.

Una matriz como esa debe eliminarse con delete[] declaración, y eso elimina la matriz completa.

Respondido 11 ago 14, 09:08

Pero verts es un vector STL. ¿Tengo que hacer eso también con los vectores? - Sara

esto-> verts [i]; elimina un elemento en la matriz que colocó dentro de verts, no verts en sí mismo - Tony el león

Aquí hay dos cosas:

  1. Como han señalado varias personas, la asignación de una matriz requiere eliminarla como una matriz. Sin embargo, creo que está enmascarando lo que realmente estás tratando de hacer aquí. Cambie su asignación para hacer un "new TriVertex"para cada artículo.

  2. Suponiendo que su vector se está almacenando TriVertex* punteros, de hecho debe eliminar cada elemento en su destructor (como ha escrito).

Por lo tanto, fijar su estrategia de asignación inicial para TriVertex los objetos deberían resolver el problema.

for(int i=0, c=0; i<vn; i++, c+=3)
{
    TriVertex *vertsaux = new TriVertex;

    vertsaux->SetId(i);
    vertsaux->SetCoords0(Vector3(vs[c], vs[c+1], vs[c+2]));

    //Initializing texture vertices
    vertsaux->SetTextureCoords(Vector2(0.0f, 0.0f));
    verts[i] = vertsaux;
}

Respondido 11 ago 14, 09:08

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.