c++ - Cómo borrar elementos de boost:: ptr_vector
ptr-vector (6)
Así que estoy tratando de deshacerme de mi std :: vector usando boost :: ptr_vector. Ahora trato de eliminar un elemento de uno, y también eliminé el elemento eliminado. Lo más obvio para mí fue hacer:
class A
{ int m; };
boost::ptr_vector<A> vec;
A* a = new A;
vec.push_back(a);
vec.erase(a);
Pero esto ni siquiera compilará (ver más abajo el mensaje de error completo). Probé la expresión borrar / eliminar como lo haría en un std :: vector, pero todos los algoritmos de boost :: ptr_vector son ligeramente diferentes de los de std :: vector.
Entonces mis preguntas:
- ¿Cómo elimino un puntero de un ptr_vector?
- ¿Todavía tengo que eliminar manualmente () ese elemento que eliminé?
Error del compilador:
1>------ Build started: Project: ptr_vector_test, Configuration: Debug Win32 ------
1>Compiling...
1>ptr_vector_test.cpp
1>c:/users/rvanhout/svn/trunk/thirdparty/boost/range/const_iterator.hpp(37) : error C2825: ''C'': must be a class or namespace when followed by ''::''
1> c:/users/rvanhout/svn/trunk/thirdparty/boost/mpl/eval_if.hpp(63) : see reference to class template instantiation ''boost::range_const_iterator<C>'' being compiled
1> with
1> [
1> C=A *
1> ]
1> c:/users/rvanhout/svn/trunk/thirdparty/boost/range/iterator.hpp(63) : see reference to class template instantiation ''boost::mpl::eval_if_c<C,F1,F2>'' being compiled
1> with
1> [
1> C=true,
1> F1=boost::range_const_iterator<A *>,
1> F2=boost::range_mutable_iterator<A *const >
1> ]
1> c:/users/rvanhout/svn/trunk/thirdparty/boost/ptr_container/detail/reversible_ptr_container.hpp(506) : see reference to class template instantiation ''boost::range_iterator<C>'' being compiled
1> with
1> [
1> C=A *const
1> ]
1> c:/tmp/ptr_vector_test/ptr_vector_test.cpp(21) : see reference to function template instantiation ''boost::void_ptr_iterator<VoidIter,T> boost::ptr_container_detail::reversible_ptr_container<Config,CloneAllocator>::erase<A*>(const Range &)'' being compiled
1> with
1> [
1> VoidIter=std::_Vector_iterator<void *,std::allocator<void *>>,
1> T=A,
1> Config=boost::ptr_container_detail::sequence_config<A,std::vector<void *,std::allocator<void *>>>,
1> CloneAllocator=boost::heap_clone_allocator,
1> Range=A *
1> ]
1>c:/users/rvanhout/svn/trunk/thirdparty/boost/range/const_iterator.hpp(37) : error C2039: ''const_iterator'' : is not a member of ''`global namespace''''
1>c:/users/rvanhout/svn/trunk/thirdparty/boost/range/const_iterator.hpp(37) : error C2146: syntax error : missing '';'' before identifier ''type''
1>c:/users/rvanhout/svn/trunk/thirdparty/boost/range/const_iterator.hpp(37) : error C2208: ''boost::type'' : no members defined using this type
1>c:/users/rvanhout/svn/trunk/thirdparty/boost/range/const_iterator.hpp(37) : fatal error C1903: unable to recover from previous error(s); stopping compilation
1>Build log was saved at "file://c:/tmp/ptr_vector_test/Debug/BuildLog.htm"
1>ptr_vector_test - 5 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Bueno, puedes hacer eso con un std :: vector cualquiera.
En ambos casos, borrar toma un iterador como parámetro.
Entonces, antes de poder borrar algo de un vector (o un ptr_vector) necesitas localizarlo.
También tenga en cuenta que ptr_vector trata su contenido como si hubiera almacenado un objeto, no un puntero. Entonces cualquier búsqueda se realiza a través del objeto.
Así que básicamente
std::vector<A> x;
std::ptr_vector<A> y;
// These two object should behave in exactly the same way.
// The ONLY difference is inserting values which for y are pointers.
// Y take ownership of the pointer and all subsequent acesses to the
// members of y look like they are objects
Ejemplo:
#include <boost/ptr_container/ptr_vector.hpp>
#include <vector>
class A
{ int m;
public:
A(int x):m(x) {}
bool operator==(A const& rhs) {return m = rhs.m;}
};
int main()
{
boost::ptr_vector<A> x;
x.push_back(new A(1));
x.erase(std::find(x.begin(),x.end(),A(1)));
std::vector<A> y;
y.push_back(A(2));
y.erase(std::find(y.begin(),y.end(),A(2)));
// To find an exact pointer don''t modify the equality.
// Use find_if and pass a predicate that tests for a pointer
A* a = new A(3);
boost:ptr_Vector<A> z;
z.push_back(a);
z.erase(std::find_if(y.begin(),y.end(),CheckPointerValue(a));
}
struct CheckPointerValue
{
CheckPointerValue(A* a):anA(a) {}
bool operator()(A const& x) { return &X == anA;}
private:
A* anA;
};
Creo que quieres llamar a .release () en el vector en lugar de borrar. Eso elimina la entrada y elimina la memoria.
Consulte la sección "Nuevas funciones" para más detalles en el tutorial o verifique la referencia .
Alternativamente, necesita obtener un iterador a un elemento para llamar a erase (), estoy seguro de que un A * cuenta en términos de un ptr_vector.
La semántica de ptr_vector
es muy similar a un vector
regular. Tienes que encontrar un elemento antes de poder borrarlo.
Necesita usar el método erase_if miembro con un predicado adecuado. No es necesario eliminar el puntero, el contenedor tiene propiedad.
struct delete_a {
bool operator()(boost::ptr_vector<A>::value_type inA) {
return inA == a;
}
}
vec.erase_if(delete_a());
(tenga en cuenta que este es solo un ejemplo elegido para simplificar, para tal situación en código real, supongo que uno debería escribir un bind / equal_to combo adecuado, o usar lambda)
O, como alternativa, liberación de llamada en el iterador correcto, si aún desea usar el objeto.
Puede usar el método de la plantilla erase_if.
vec.erase_if( predicate() );
Lo curioso: STL :: vector <> es un contenedor de acceso aleatorio , lo que significa que utiliza Iteradores de acceso aleatorio .
Así que vec.erase (vec.begin () + N) eliminará el elemento en el índice N.
Tenga en cuenta que al hacerlo se rompe todo el meme del iterador y ya no se puede cambiar trivialmente entre vectores y listas ...