c++ boost ptr-vector

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