所以我试图通过使用boost :: ptr_vector来摆脱我的std :: vector。现在我正在尝试从一个元素中删除元素,并删除已删除的元素。对我来说最明显的事情是:
class A
{ int m; };
boost::ptr_vector<A> vec;
A* a = new A;
vec.push_back(a);
vec.erase(a);
但是这甚至都不会编译(请参阅下面的完整错误消息)。我已经尝试过删除/删除习惯用法,就像我在std :: vector上所做的那样,但是boost :: ptr_vector的所有算法都与std :: vector中的算法略有不同。
所以我的问题:
编译错误:
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 ==========
答案 0 :(得分:9)
你可以用std :: vector做到这一点。
在两种情况下,erase都将迭代器作为参数 因此,在您从矢量(或ptr_vector)中删除某些内容之前,您需要找到它。
另请注意,ptr_vector将其内容视为已存储对象而非存储指针。所以任何搜索都是通过对象完成的。
所以基本上
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
示例:
#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;
};
答案 1 :(得分:3)
我认为你想在向量上调用.release()而不是擦除。这将删除条目并删除内存。
有关the tutorial中的详细信息,请参阅“新功能”部分,或查看the reference。
或者,您需要获取元素的迭代器才能调用erase(),我确定A *会根据ptr_vector计算。
答案 2 :(得分:1)
您可以使用erase_if模板方法。
vec.erase_if( predicate() );
答案 3 :(得分:1)
ptr_vector
的语义与常规vector
非常相似。你必须先找到一个元素才能删除它。
答案 4 :(得分:1)
奇怪的是:STL::vector<>是Random Access Container,意味着它使用了Random Access Iterators。
所以 vec.erase(vec.begin()+ N)将删除索引N处的元素。
请注意,这样做会打破整个迭代器模因,你不能再轻易地在矢量和列表之间切换......
答案 5 :(得分:0)
您需要将成员erase_if方法与合适的谓词一起使用。没有必要删除指针,容器有所有权。
struct delete_a {
bool operator()(boost::ptr_vector<A>::value_type inA) {
return inA == a;
}
}
vec.erase_if(delete_a());
(注意这只是为了简单而选择的一个例子,对于实际代码中的这种情况,我想有人会编写一个合适的bind / equal_to组合,或者使用lambda)
或者,作为替代方案,如果您仍想使用该对象,请在正确的迭代器上调用release。